Skip to content Skip to sidebar Skip to footer

Trying All Combinations Of Operations On List Of Variables

I have a list of values like: values = [1, 2, 3, 4] and I want to try all combinations on this list like: 1 + 2 1 + 3 1 + 4 1 * 2 1 * 3 1 * 4 1 + 2 * 3 1 + 2 * 4 1 + 3 * 4 etc. W

Solution 1:

Here's a recursive solution that builds the expression from numbers & operators and then uses eval to calculate it:

vals = [1, 2, 3]
operators = ['+', '*', '-', '/']

defexpressions(values):
    # Base case, only one value leftiflen(values) == 1:
        yield values

    # Iterate over the indexesfor i inrange(len(values)):
        # Pop value from given index and store the remaining values# to be used with next recursion
        forward = values[:]
        val = forward.pop(i)

        # Yield all value, operator, subexpression combinationsfor op in operators:
            for rest in expressions(forward):
                yield [val, op] + rest

for expr in expressions(vals):
    expr = ' '.join(str(x) for x in expr)
    print('{} = {}'.format(expr, eval(expr)))

Output (partial):

1 + 2 + 3 = 6
1 + 2 * 3 = 7
1 + 2 - 3 = 0
1 + 2 / 3 = 1.6666666666666665
1 + 3 + 2 = 6
1 + 3 * 2 = 7
1 + 3 - 2 = 2
1 + 3 / 2 = 2.5
1 * 2 + 3 = 5
1 * 2 * 3 = 6
1 * 2 - 3 = -1
1 * 2 / 3 = 0.6666666666666666
1 * 3 + 2 = 5
1 * 3 * 2 = 6
1 * 3 - 2 = 1
1 * 3 / 2 = 1.5
1 - 2 + 3 = 2
1 - 2 * 3 = -5
1 - 2 - 3 = -4

Solution 2:

How about this one (since order of the operands and operators does matter, we must use permutation) ?

from itertools import chain, permutations

defpowerset(iterable):
  xs = list(iterable)
  return chain.from_iterable(permutations(xs,n) for n inrange(len(xs)+1) )

lst_expr = []
for operands inmap(list, powerset(['1','2','3','4'])):
    n = len(operands)
    #print operandsif n > 1:
        all_operators = map(list, permutations(['+','-','*','/'],n-1))
        #print all_operators, operandsfor operators in all_operators:
            exp = operands[0]
            i = 1for operator in operators:
                exp += operator + operands[i]
                i += 1
            lst_expr += [exp]

print', '.join(lst_expr)

with the following output:

1+2, 1-2, 1*2, 1/2, 1+3, 1-3, 1*3, 1/3, 1+4, 1-4, 1*4, 1/4, 2+1, 2-1, 2*1, 2/1, 2+3, 2-3, 2*3, 2/3, 2+4, 2-4, 2*4, 2/4, 3+1, 3-1, 3*1, 3/1, 3+2, 3-2, 3*2, 3/2, 3+4, 3-4, 3*4, 3/4, 4+1, 4-1, 4*1, 4/1, 4+2, 4-2, 4*2, 4/2, 4+3, 4-3, 4*3, 4/3, 1+2-3, 1+2*3, 1+2/3, 1-2+3, 1-2*3, 1-2/3, 1*2+3, 1*2-3, 1*2/3, 1/2+3, 1/2-3, 1/2*3, 1+2-4, 1+2*4, 1+2/4, 1-2+4, 1-2*4, 1-2/4, 1*2+4, 1*2-4, 1*2/4, 1/2+4, 1/2-4, 1/2*4, 1+3-2, 1+3*2, 1+3/2, 1-3+2, 1-3*2, 1-3/2, 1*3+2, 1*3-2, 1*3/2, 1/3+2, 1/3-2, 1/3*2, 1+3-4, 1+3*4, 1+3/4, 1-3+4, 1-3*4, 1-3/4, 1*3+4, 1*3-4, 1*3/4, 1/3+4, 1/3-4, 1/3*4, 1+4-2, 1+4*2, 1+4/2, 1-4+2, 1-4*2, 1-4/2, 1*4+2, 1*4-2, 1*4/2, 1/4+2, 1/4-2, 1/4*2, 1+4-3, 1+4*3, 1+4/3, 1-4+3, 1-4*3, 1-4/3, 1*4+3, 1*4-3, 1*4/3, 1/4+3, 1/4-3, 1/4*3, 2+1-3, 2+1*3, 2+1/3, 2-1+3, 2-1*3, 2-1/3, 2*1+3, 2*1-3, 2*1/3, 2/1+3, 2/1-3, 2/1*3, 2+1-4, 2+1*4, 2+1/4, 2-1+4, 2-1*4, 2-1/4, 2*1+4, 2*1-4, 2*1/4, 2/1+4, 2/1-4, 2/1*4, 2+3-1, 2+3*1, 2+3/1, 2-3+1, 2-3*1, 2-3/1, 2*3+1, 2*3-1, 2*3/1, 2/3+1, 2/3-1, 2/3*1, 2+3-4, 2+3*4, 2+3/4, 2-3+4, 2-3*4, 2-3/4, 2*3+4, 2*3-4, 2*3/4, 2/3+4, 2/3-4, 2/3*4, 2+4-1, 2+4*1, 2+4/1, 2-4+1, 2-4*1, 2-4/1, 2*4+1, 2*4-1, 2*4/1, 2/4+1, 2/4-1, 2/4*1, 2+4-3, 2+4*3, 2+4/3, 2-4+3, 2-4*3, 2-4/3, 2*4+3, 2*4-3, 2*4/3, 2/4+3, 2/4-3, 2/4*3, 3+1-2, 3+1*2, 3+1/2, 3-1+2, 3-1*2, 3-1/2, 3*1+2, 3*1-2, 3*1/2, 3/1+2, 3/1-2, 3/1*2, 3+1-4, 3+1*4, 3+1/4, 3-1+4, 3-1*4, 3-1/4, 3*1+4, 3*1-4, 3*1/4, 3/1+4, 3/1-4, 3/1*4, 3+2-1, 3+2*1, 3+2/1, 3-2+1, 3-2*1, 3-2/1, 3*2+1, 3*2-1, 3*2/1, 3/2+1, 3/2-1, 3/2*1, 3+2-4, 3+2*4, 3+2/4, 3-2+4, 3-2*4, 3-2/4, 3*2+4, 3*2-4, 3*2/4, 3/2+4, 3/2-4, 3/2*4, 3+4-1, 3+4*1, 3+4/1, 3-4+1, 3-4*1, 3-4/1, 3*4+1, 3*4-1, 3*4/1, 3/4+1, 3/4-1, 3/4*1, 3+4-2, 3+4*2, 3+4/2, 3-4+2, 3-4*2, 3-4/2, 3*4+2, 3*4-2, 3*4/2, 3/4+2, 3/4-2, 3/4*2, 4+1-2, 4+1*2, 4+1/2, 4-1+2, 4-1*2, 4-1/2, 4*1+2, 4*1-2, 4*1/2, 4/1+2, 4/1-2, 4/1*2, 4+1-3, 4+1*3, 4+1/3, 4-1+3, 4-1*3, 4-1/3, 4*1+3, 4*1-3, 4*1/3, 4/1+3, 4/1-3, 4/1*3, 4+2-1, 4+2*1, 4+2/1, 4-2+1, 4-2*1, 4-2/1, 4*2+1, 4*2-1, 4*2/1, 4/2+1, 4/2-1, 4/2*1, 4+2-3, 4+2*3, 4+2/3, 4-2+3, 4-2*3, 4-2/3, 4*2+3, 4*2-3, 4*2/3, 4/2+3, 4/2-3, 4/2*3, 4+3-1, 4+3*1, 4+3/1, 4-3+1, 4-3*1, 4-3/1, 4*3+1, 4*3-1, 4*3/1, 4/3+1, 4/3-1, 4/3*1, 4+3-2, 4+3*2, 4+3/2, 4-3+2, 4-3*2, 4-3/2, 4*3+2, 4*3-2, 4*3/2, 4/3+2, 4/3-2, 4/3*2, 1+2-3*4, 1+2-3/4, 1+2*3-4, 1+2*3/4, 1+2/3-4, 1+2/3*4, 1-2+3*4, 1-2+3/4, 1-2*3+4, 1-2*3/4, 1-2/3+4, 1-2/3*4, 1*2+3-4, 1*2+3/4, 1*2-3+4, 1*2-3/4, 1*2/3+4, 1*2/3-4, 1/2+3-4, 1/2+3*4, 1/2-3+4, 1/2-3*4, 1/2*3+4, 1/2*3-4, 1+2-4*3, 1+2-4/3, 1+2*4-3, 1+2*4/3, 1+2/4-3, 1+2/4*3, 1-2+4*3, 1-2+4/3, 1-2*4+3, 1-2*4/3, 1-2/4+3, 1-2/4*3, 1*2+4-3, 1*2+4/3, 1*2-4+3, 1*2-4/3, 1*2/4+3, 1*2/4-3, 1/2+4-3, 1/2+4*3, 1/2-4+3, 1/2-4*3, 1/2*4+3, 1/2*4-3, 1+3-2*4, 1+3-2/4, 1+3*2-4, 1+3*2/4, 1+3/2-4, 1+3/2*4, 1-3+2*4, 1-3+2/4, 1-3*2+4, 1-3*2/4, 1-3/2+4, 1-3/2*4, 1*3+2-4, 1*3+2/4, 1*3-2+4, 1*3-2/4, 1*3/2+4, 1*3/2-4, 1/3+2-4, 1/3+2*4, 1/3-2+4, 1/3-2*4, 1/3*2+4, 1/3*2-4, 1+3-4*2, 1+3-4/2, 1+3*4-2, 1+3*4/2, 1+3/4-2, 1+3/4*2, 1-3+4*2, 1-3+4/2, 1-3*4+2, 1-3*4/2, 1-3/4+2, 1-3/4*2, 1*3+4-2, 1*3+4/2, 1*3-4+2, 1*3-4/2, 1*3/4+2, 1*3/4-2, 1/3+4-2, 1/3+4*2, 1/3-4+2, 1/3-4*2, 1/3*4+2, 1/3*4-2, 1+4-2*3, 1+4-2/3, 1+4*2-3, 1+4*2/3, 1+4/2-3, 1+4/2*3, 1-4+2*3, 1-4+2/3, 1-4*2+3, 1-4*2/3, 1-4/2+3, 1-4/2*3, 1*4+2-3, 1*4+2/3, 1*4-2+3, 1*4-2/3, 1*4/2+3, 1*4/2-3, 1/4+2-3, 1/4+2*3, 1/4-2+3, 1/4-2*3, 1/4*2+3, 1/4*2-3, 1+4-3*2, 1+4-3/2, 1+4*3-2, 1+4*3/2, 1+4/3-2, 1+4/3*2, 1-4+3*2, 1-4+3/2, 1-4*3+2, 1-4*3/2, 1-4/3+2, 1-4/3*2, 1*4+3-2, 1*4+3/2, 1*4-3+2, 1*4-3/2, 1*4/3+2, 1*4/3-2, 1/4+3-2, 1/4+3*2, 1/4-3+2, 1/4-3*2, 1/4*3+2, 1/4*3-2, 2+1-3*4, 2+1-3/4, 2+1*3-4, 2+1*3/4, 2+1/3-4, 2+1/3*4, 2-1+3*4, 2-1+3/4, 2-1*3+4, 2-1*3/4, 2-1/3+4, 2-1/3*4, 2*1+3-4, 2*1+3/4, 2*1-3+4, 2*1-3/4, 2*1/3+4, 2*1/3-4, 2/1+3-4, 2/1+3*4, 2/1-3+4, 2/1-3*4, 2/1*3+4, 2/1*3-4, 2+1-4*3, 2+1-4/3, 2+1*4-3, 2+1*4/3, 2+1/4-3, 2+1/4*3, 2-1+4*3, 2-1+4/3, 2-1*4+3, 2-1*4/3, 2-1/4+3, 2-1/4*3, 2*1+4-3, 2*1+4/3, 2*1-4+3, 2*1-4/3, 2*1/4+3, 2*1/4-3, 2/1+4-3, 2/1+4*3, 2/1-4+3, 2/1-4*3, 2/1*4+3, 2/1*4-3, 2+3-1*4, 2+3-1/4, 2+3*1-4, 2+3*1/4, 2+3/1-4, 2+3/1*4, 2-3+1*4, 2-3+1/4, 2-3*1+4, 2-3*1/4, 2-3/1+4, 2-3/1*4, 2*3+1-4, 2*3+1/4, 2*3-1+4, 2*3-1/4, 2*3/1+4, 2*3/1-4, 2/3+1-4, 2/3+1*4, 2/3-1+4, 2/3-1*4, 2/3*1+4, 2/3*1-4, 2+3-4*1, 2+3-4/1, 2+3*4-1, 2+3*4/1, 2+3/4-1, 2+3/4*1, 2-3+4*1, 2-3+4/1, 2-3*4+1, 2-3*4/1, 2-3/4+1, 2-3/4*1, 2*3+4-1, 2*3+4/1, 2*3-4+1, 2*3-4/1, 2*3/4+1, 2*3/4-1, 2/3+4-1, 2/3+4*1, 2/3-4+1, 2/3-4*1, 2/3*4+1, 2/3*4-1, 2+4-1*3, 2+4-1/3, 2+4*1-3, 2+4*1/3, 2+4/1-3, 2+4/1*3, 2-4+1*3, 2-4+1/3, 2-4*1+3, 2-4*1/3, 2-4/1+3, 2-4/1*3, 2*4+1-3, 2*4+1/3, 2*4-1+3, 2*4-1/3, 2*4/1+3, 2*4/1-3, 2/4+1-3, 2/4+1*3, 2/4-1+3, 2/4-1*3, 2/4*1+3, 2/4*1-3, 2+4-3*1, 2+4-3/1, 2+4*3-1, 2+4*3/1, 2+4/3-1, 2+4/3*1, 2-4+3*1, 2-4+3/1, 2-4*3+1, 2-4*3/1, 2-4/3+1, 2-4/3*1, 2*4+3-1, 2*4+3/1, 2*4-3+1, 2*4-3/1, 2*4/3+1, 2*4/3-1, 2/4+3-1, 2/4+3*1, 2/4-3+1, 2/4-3*1, 2/4*3+1, 2/4*3-1, 3+1-2*4, 3+1-2/4, 3+1*2-4, 3+1*2/4, 3+1/2-4, 3+1/2*4, 3-1+2*4, 3-1+2/4, 3-1*2+4, 3-1*2/4, 3-1/2+4, 3-1/2*4, 3*1+2-4, 3*1+2/4, 3*1-2+4, 3*1-2/4, 3*1/2+4, 3*1/2-4, 3/1+2-4, 3/1+2*4, 3/1-2+4, 3/1-2*4, 3/1*2+4, 3/1*2-4, 3+1-4*2, 3+1-4/2, 3+1*4-2, 3+1*4/2, 3+1/4-2, 3+1/4*2, 3-1+4*2, 3-1+4/2, 3-1*4+2, 3-1*4/2, 3-1/4+2, 3-1/4*2, 3*1+4-2, 3*1+4/2, 3*1-4+2, 3*1-4/2, 3*1/4+2, 3*1/4-2, 3/1+4-2, 3/1+4*2, 3/1-4+2, 3/1-4*2, 3/1*4+2, 3/1*4-2, 3+2-1*4, 3+2-1/4, 3+2*1-4, 3+2*1/4, 3+2/1-4, 3+2/1*4, 3-2+1*4, 3-2+1/4, 3-2*1+4, 3-2*1/4, 3-2/1+4, 3-2/1*4, 3*2+1-4, 3*2+1/4, 3*2-1+4, 3*2-1/4, 3*2/1+4, 3*2/1-4, 3/2+1-4, 3/2+1*4, 3/2-1+4, 3/2-1*4, 3/2*1+4, 3/2*1-4, 3+2-4*1, 3+2-4/1, 3+2*4-1, 3+2*4/1, 3+2/4-1, 3+2/4*1, 3-2+4*1, 3-2+4/1, 3-2*4+1, 3-2*4/1, 3-2/4+1, 3-2/4*1, 3*2+4-1, 3*2+4/1, 3*2-4+1, 3*2-4/1, 3*2/4+1, 3*2/4-1, 3/2+4-1, 3/2+4*1, 3/2-4+1, 3/2-4*1, 3/2*4+1, 3/2*4-1, 3+4-1*2, 3+4-1/2, 3+4*1-2, 3+4*1/2, 3+4/1-2, 3+4/1*2, 3-4+1*2, 3-4+1/2, 3-4*1+2, 3-4*1/2, 3-4/1+2, 3-4/1*2, 3*4+1-2, 3*4+1/2, 3*4-1+2, 3*4-1/2, 3*4/1+2, 3*4/1-2, 3/4+1-2, 3/4+1*2, 3/4-1+2, 3/4-1*2, 3/4*1+2, 3/4*1-2, 3+4-2*1, 3+4-2/1, 3+4*2-1, 3+4*2/1, 3+4/2-1, 3+4/2*1, 3-4+2*1, 3-4+2/1, 3-4*2+1, 3-4*2/1, 3-4/2+1, 3-4/2*1, 3*4+2-1, 3*4+2/1, 3*4-2+1, 3*4-2/1, 3*4/2+1, 3*4/2-1, 3/4+2-1, 3/4+2*1, 3/4-2+1, 3/4-2*1, 3/4*2+1, 3/4*2-1, 4+1-2*3, 4+1-2/3, 4+1*2-3, 4+1*2/3, 4+1/2-3, 4+1/2*3, 4-1+2*3, 4-1+2/3, 4-1*2+3, 4-1*2/3, 4-1/2+3, 4-1/2*3, 4*1+2-3, 4*1+2/3, 4*1-2+3, 4*1-2/3, 4*1/2+3, 4*1/2-3, 4/1+2-3, 4/1+2*3, 4/1-2+3, 4/1-2*3, 4/1*2+3, 4/1*2-3, 4+1-3*2, 4+1-3/2, 4+1*3-2, 4+1*3/2, 4+1/3-2, 4+1/3*2, 4-1+3*2, 4-1+3/2, 4-1*3+2, 4-1*3/2, 4-1/3+2, 4-1/3*2, 4*1+3-2, 4*1+3/2, 4*1-3+2, 4*1-3/2, 4*1/3+2, 4*1/3-2, 4/1+3-2, 4/1+3*2, 4/1-3+2, 4/1-3*2, 4/1*3+2, 4/1*3-2, 4+2-1*3, 4+2-1/3, 4+2*1-3, 4+2*1/3, 4+2/1-3, 4+2/1*3, 4-2+1*3, 4-2+1/3, 4-2*1+3, 4-2*1/3, 4-2/1+3, 4-2/1*3, 4*2+1-3, 4*2+1/3, 4*2-1+3, 4*2-1/3, 4*2/1+3, 4*2/1-3, 4/2+1-3, 4/2+1*3, 4/2-1+3, 4/2-1*3, 4/2*1+3, 4/2*1-3, 4+2-3*1, 4+2-3/1, 4+2*3-1, 4+2*3/1, 4+2/3-1, 4+2/3*1, 4-2+3*1, 4-2+3/1, 4-2*3+1, 4-2*3/1, 4-2/3+1, 4-2/3*1, 4*2+3-1, 4*2+3/1, 4*2-3+1, 4*2-3/1, 4*2/3+1, 4*2/3-1, 4/2+3-1, 4/2+3*1, 4/2-3+1, 4/2-3*1, 4/2*3+1, 4/2*3-1, 4+3-1*2, 4+3-1/2, 4+3*1-2, 4+3*1/2, 4+3/1-2, 4+3/1*2, 4-3+1*2, 4-3+1/2, 4-3*1+2, 4-3*1/2, 4-3/1+2, 4-3/1*2, 4*3+1-2, 4*3+1/2, 4*3-1+2, 4*3-1/2, 4*3/1+2, 4*3/1-2, 4/3+1-2, 4/3+1*2, 4/3-1+2, 4/3-1*2, 4/3*1+2, 4/3*1-2, 4+3-2*1, 4+3-2/1, 4+3*2-1, 4+3*2/1, 4+3/2-1, 4+3/2*1, 4-3+2*1, 4-3+2/1, 4-3*2+1, 4-3*2/1, 4-3/2+1, 4-3/2*1, 4*3+2-1, 4*3+2/1, 4*3-2+1, 4*3-2/1, 4*3/2+1, 4*3/2-1, 4/3+2-1, 4/3+2*1, 4/3-2+1, 4/3-2*1, 4/3*2+1, 4/3*2-1

Solution 3:

My solution consumes a list of values and thus applies operations on the order with which arguments are given, as an alternative to normal arithmetic evaluation order. For example, 1 + 3 + 5 + 7, would be (((1 + 3) +5) + 7). However, it takes all possible permutations of values, so all possibilities are listed anyway. It also allows one to give any operations as parameters, even lambda expressions.

I use itertools.

from itertools import combinations_with_replacement
from itertools import permutations
from itertools import product
from itertools import chain

To display all expressions we call:

def list_all(operations, values):
    if len(values) ==1:
        returnvalues
    permutes = []
    ops = []
    expressions = []
    # for4values we want combinations with2, 3and4 values.
    forsubsetinrange(2, len(values)+1):
        # One could use combinations instead of permutations if all ops
        # where know to be transitive.
        permutes.append(list(permutations(values, subset)))
        ops.append(list(combinations_with_replacement(operations, subset-1)))
    for o, v in zip(ops, permutes):
        expressions.append(list(itertools.product(o, v)))
    return expressions

And to evaluate them, execute takes the output of list_all:

def execute(expressions):
    results = []
    # Flatten all expressions into a single iterator
    for ops, arguments in chain.from_iterable(expressions):
        oplist = list(ops)
        arglist = list(arguments)
        res = oplist.pop(0)(arglist.pop(0), arglist.pop(0))
        while len(arglist) > 0:
            res = oplist.pop(0)(res, arglist.pop(0))
        results.append(res)
    return results

Example usage:

from operator import add
from operator import sub
import pprint
expressions = list_all([add, sub, lambda x,y : sqrt(x*x + y*y)], [1, 2, 3, 4])
results = execute(expressions)

# Display list with operators, arguments and results.
pprint.pprint(zip(chain.from_iterable(expressions), results))

Solution 4:

Below is the simpler and cleaner code to achieve this using operator and itertools.

Also check regarding why not to use eval: Is using eval in Python a bad practice?

from itertools import product, combinations, chain
from operator import add, sub, mul, div, mod, floordiv

my_list = [1, 2, 3, 4, 0]
my_operations = {'+': add, '-': sub, '/': div, '*': mul, '%': mod, '//': floordiv}

for nums, action in chain(product([i for i in combinations(my_list, 2)], my_operations)):
    try:
        result = my_operations[action](nums[0], nums[1])
    except ZeroDivisionError:
        result = 'infinite'finally:
        print'{} {} {} = {}'.format(nums[0], action, nums[1], result)

Below is the output of above code:

1// 2 = 01 % 2 = 11 + 2 = 31 * 2 = 21 - 2 = -11 / 2 = 01// 3 = 01 % 3 = 11 + 3 = 41 * 3 = 31 - 3 = -21 / 3 = 01// 4 = 01 % 4 = 11 + 4 = 51 * 4 = 41 - 4 = -31 / 4 = 01// 0 = infinite1 % 0 = infinite
1 + 0 = 11 * 0 = 01 - 0 = 11 / 0 = infinite
2// 3 = 02 % 3 = 22 + 3 = 52 * 3 = 62 - 3 = -12 / 3 = 02// 4 = 02 % 4 = 22 + 4 = 62 * 4 = 82 - 4 = -22 / 4 = 02// 0 = infinite2 % 0 = infinite
2 + 0 = 22 * 0 = 02 - 0 = 22 / 0 = infinite
3// 4 = 03 % 4 = 33 + 4 = 73 * 4 = 123 - 4 = -13 / 4 = 03// 0 = infinite3 % 0 = infinite
3 + 0 = 33 * 0 = 03 - 0 = 33 / 0 = infinite
4// 0 = infinite4 % 0 = infinite
4 + 0 = 44 * 0 = 04 - 0 = 44 / 0 = infinite

Post a Comment for "Trying All Combinations Of Operations On List Of Variables"