Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Function for recognize quantity of unique combinations
-
Hello pythonista community. Can someone adwise me formula for recognize quantity of unique combinations when you count to some max digit with sign "-" (minus)? Answer can't be under zero.
Example1:
sign = '-'
max = 2
2-2
2-1
1-1- we have only three unique combinations.
Example2:
answer can't be upper max:
max = 2
1+1- we have only one unique example.
I already have formula for two signs "+-": unic_col=max**2
But i need formula for '+' and '-'
And maybe someone know for:
+-×
+-/
+-×/
/×So, i need function like that:
def uniques_col(operators, max):
if operators == '+-':
return max**2
elif operators == '+':
return .....
elif operators == '-':
return .....
elif operators == '+-×':
return .....
...... -
@lyubomyr83, I am confused by the problem definition. What is
max
?- Largest digit to be used in the calculations, or
- largest allowed result of a calculation, or
- both of the above?
Also, what do you need this for?
-
@mikael
Max - variable count to, for example 100.
So i need count quantity uniques examples for some mathematic operator, in my case '+' or '-'
I can't have example 98+10 or 25-50
Max example result must be under 100 or equal
Minimum example result must be under 0 -
-
@lyubomyr83 sorry if I didn't understand correctly, do you want a formula or a script like
def uniques_col(operators, max): n = 0 if operators == '+': for i in range(1,max): for j in range(i,max-i+1): n += 1 print(i,operators,j,'=',i+j) elif operators == '-': for i in range(1,max+1): for j in range(1,i+1): n += 1 print(i,operators,j,'=',i-j) return n op = input('operator') v = int(input(op)) print(uniques_col(op,v))
-
@lyubomyr83 Something like this?
# -*- coding: utf-8 -*- """ Test solution for https://forum.omz-software.com/topic/6159/function-for-recognize-quantity-of-unique-combinations """ import operator OPERATORS = { "+": operator.add, "-": operator.sub, "*": operator.mul, "×": operator.mul, } def eval_eq(a, op, b): return OPERATORS[op](a, b) def uniques_col(operators, max): if len(operators) == 0: # we could also just return (max - 1) raise ValueError("No operators given!") elif len(operators) > 1: # the code in the question makes it look like we should add # the number of individual operator combinations if multiple # operators are given. n = 0 for op in operators: n += uniques_col(op, max) return n else: combinations = [] for a in range(max, 0, -1): # for a in range(1, max + 1): for b in range(max, 0, -1): # for b in range(1, max + 1): res = eval_eq(a, operators, b) if res > max: # should this be result >= max? continue if res < 0: # result cant be under 0 continue comb = (a, operators, b) print(comb) if comb not in combinations: combinations.append(comb) return len(combinations) if __name__ == "__main__": testdata = [ # format: operators, max, expected ("-", 2, 3), ("+", 2, 1), ("+-", 2, 4), ("+-", 3, 9), ("+-*", 3, None), ] for ops, m, exp in testdata: n = uniques_col(ops, m) print("uniques_col({m}, '{o}') -> {r}; expected {e}".format(m=m, o=ops, r=n, e=exp))
This produced this output:
(2, '-', 2) (2, '-', 1) (1, '-', 1) uniques_col(2, '-') -> 3; expected 3 (1, '+', 1) uniques_col(2, '+') -> 1; expected 1 (1, '+', 1) (2, '-', 2) (2, '-', 1) (1, '-', 1) uniques_col(2, '+-') -> 4; expected 4 (2, '+', 1) (1, '+', 2) (1, '+', 1) (3, '-', 3) (3, '-', 2) (3, '-', 1) (2, '-', 2) (2, '-', 1) (1, '-', 1) uniques_col(3, '+-') -> 9; expected 9 (2, '+', 1) (1, '+', 2) (1, '+', 1) (3, '-', 3) (3, '-', 2) (3, '-', 1) (2, '-', 2) (2, '-', 1) (1, '-', 1) (3, '*', 1) (2, '*', 1) (1, '*', 3) (1, '*', 2) (1, '*', 1) uniques_col(3, '+-*') -> 14; expected None
Your question is kind of hard to understand, so I am not sure this solution is correct...
-
@bennr01, nice! Couple of possible, nit-picky refinements:
Do not use
max
as an argument name.Instead of for loops, generate the candidates with:
candidates = itertools.product( range(max_int+1), operations, range(max_int+1) )
-
@mikael said:
Do not use
max
as an argument name.Generally true, but in this case I wanted to preserve the original function signature used in the question.
Instead of for loops, generate the candidates with:
candidates = itertools.product( range(max_int+1), operations, range(max_int+1) )
Yeah, that is way cleaner.
-
@bennr01, just read an article on functional programming in Python, so one step further:
import itertools import operator OPERATORS = { "+": operator.add, "-": operator.sub, "*": operator.mul, "×": operator.mul, } def uniques_col(operators, max_value): return filter( lambda c: 0 <= OPERATORS[c[1]](c[0], c[2]) <= max_value, itertools.product( range(1, max_value+1), operators, range(1, max_value+1) ) ) print(list(uniques_col('+-', 2)))
-
@lyubomyr83, not an answer to your question, but maybe you can use these brute-force versions to check the formulas you come up with?
-
@bennr01, with one more fancy function:
import itertools def uniques_col(operators, max_value): possibles = lambda: range(1, max_value+1) return filter( lambda c: 0 <= eval(''.join(map(str, c))) <= max_value, itertools.product(possibles(), operators, possibles()) ) print(list(uniques_col('+-', 2)))
-
@cvp, thank you all for help!!!
With your function i receive right col for '-', but not for '+':def uniques_col(operators, max):
n = 0
if operators == '+':
for i in range(1,max):
for j in range(i,max-i+1):
n += 1
print(i,operators,j,'=',i+j)
elif operators == '-':
for i in range(1,max+1):
for j in range(1,i+1):
n += 1
print(i,operators,j,'=',i-j)
return nwhile True:
op = input('operator\n')
max = int(input('max\n'))
print(uniques_col(op,max))What i receive:
operator-
max4
1 - 1 = 0
2 - 1 = 1
2 - 2 = 0
3 - 1 = 2
3 - 2 = 1
3 - 3 = 0
4 - 1 = 3
4 - 2 = 2
4 - 3 = 1
4 - 4 = 0
10
operator+
max4
1 + 1 = 2
1 + 2 = 3
1 + 3 = 4
2 + 2 = 4
4Where is 1+3 and 2+1, so for '+' i need receive 6 unique examples.
-
@lyubomyr83 said:
Where is 1+3 and 2+1,
Ok, I did believe that 1+2 is the same as 2+1, thus I did not generate it.
As I told you, I was not sure to correctly understand 😀Thus it is better to use the other script (of @bennr01 and @mikael ) because it tries all combinations.
-
-
i think you would want to check 1 to max for both numbers (consider /, max/max=1)
-
@JonB if you do that, you have to check and skip cases where i+j>max
With « my » formula, no check is needed -
-
@ccc I'm always positively surprised by the number of libraries in Python
-
I went into some kind of half-insane readability/conciseness optimization/noodling loop on this. Here’s the latest version:
from itertools import product def uniques_col(ops, maximum): number_range = range(1, maximum+1) numbers = list(map(str, number_range)) return filter( lambda c: 0 <= eval(''.join(c)) <= maximum, product(numbers, ops, numbers) ) uniques = uniques_col('+-/', 2) print(*[ f"{i+1:4}: {''.join(c)}" for i, c in enumerate(uniques)], sep='\n' )
-
numbers = [str(i + 1) for i in range(maximum)]
Read “What’s new in Python 3” for a discussion on avoiding map(), reduce(), filter().