# Function for recognize quantity of unique combinations browsing

• posted
1

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 .....
......

• posted
1

@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?

• posted
1

@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

• posted
1

@lyubomyr83 said:

Minimum example result must be under 0

upper 0

• posted
1

@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))
``````

• posted
1

@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.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...

• posted
1

@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)
)``````

• posted
0

@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.

• posted
1

@bennr01, just read an article on functional programming in Python, so one step further:

``````import itertools
import operator

OPERATORS = {
"-": operator.sub,
"*": operator.mul,
"×": operator.mul,
}

def uniques_col(operators, max_value):
return filter(
lambda c: 0 <= OPERATORS[c](c, c) <= max_value,
itertools.product(
range(1, max_value+1),
operators,
range(1, max_value+1)
)
)

print(list(uniques_col('+-', 2)))``````

• posted
0

@lyubomyr83, not an answer to your question, but maybe you can use these brute-force versions to check the formulas you come up with?

• posted
1

@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)))``````

• posted
0

@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 n

while True:
op = input('operator\n')
max = int(input('max\n'))
print(uniques_col(op,max))

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
4

Where is 1+3 and 2+1, so for '+' i need receive 6 unique examples.

• posted
0

@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.

• posted
0

@lyubomyr83

Or Change into

``````    if operators == '+':
for i in range(1,max):
for j in range(1,max-i+1):
``````

• posted
0

i think you would want to check 1 to max for both numbers (consider /, max/max=1)

• posted
0

@JonB if you do that, you have to check and skip cases where i+j>max
With « my » formula, no check is needed

• posted
0

• posted
0

@ccc I'm always positively surprised by the number of libraries in Python

• posted
1

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'
)``````

• posted
1

numbers = [str(i + 1) for i in range(maximum)]

Read “What’s new in Python 3” for a discussion on avoiding map(), reduce(), filter().

• posted
0

@ccc, you take the prize for conciseness, and readability is not bad either.

I was debating the value of separating the range of numbers (problem domain issue) and the conversion to strings (a technical implementation detail).

Internal error.

Oops! Looks like something went wrong!