Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

What would be the most straightforward way to get all these possible combinations of operations in the most succinct way possible?

I would imagine having two lists, [1,2,3,4] and [+, *, -, /] and then taking all combinations of the numbers of all lengths, and then filling in the blanks with all combinations.

So selecting [1, 2, 3] and then selecting all permutations of the operations and combining them together. This seems messy and I'm hoping there's a clearer way to code this?

like image 497
Rob Avatar asked Sep 16 '16 07:09

Rob


2 Answers

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

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

def expressions(values):
    # Base case, only one value left
    if len(values) == 1:
        yield values

    # Iterate over the indexes
    for i in range(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 combinations
        for 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
like image 151
niemmi Avatar answered Nov 15 '22 14:11

niemmi


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

from itertools import chain, permutations

def powerset(iterable):
  xs = list(iterable)
  return chain.from_iterable(permutations(xs,n) for n in range(len(xs)+1) )

lst_expr = []
for operands in map(list, powerset(['1','2','3','4'])):
    n = len(operands)
    #print operands
    if n > 1:
        all_operators = map(list, permutations(['+','-','*','/'],n-1))
        #print all_operators, operands
        for operators in all_operators:
            exp = operands[0]
            i = 1
            for 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
like image 21
Sandipan Dey Avatar answered Nov 15 '22 15:11

Sandipan Dey