How do I iterate through arithmetic operators through a static, exclude formula in Python?

I am trying to use itertools to iterate through math operators. Usually array

[1, 2, 3]

using combinations

I can get the results:

1
1,2
1,3
2,3
1,2,3

      

and etc.

I want to use this on array

from [1, 2, 3]

in such a way that:

1+2+3
1+2-3
1+2/3
1+2*3
1-2+3
1-2-3
1-2/3
1-2*3
...

      

arises and gives the results of the equation.

How can i do this?

+3


source to share


4 answers


The solution generalized to any number of operands and preserves the normal precedence of the operators:



from itertools import product

operands = [1, 2, 3, 4]
operators = [ '+', '*', '-', '//' ] # change '//' to '/' for floating point division
for opers in product(operators, repeat=len(operands)-1):
    formula = [ str(operands[0]) ]
    for op, operand in zip(opers, operands[1:]):
        formula.extend([op, str(operand)])
    formula = ' '.join(formula)
    print('{} = {}'.format(formula, eval(formula)))

      

+1


source


This is how I approach it:

import itertools
import operator

      

First, create a list of all possible combinations:

funcs = [operator.add, operator.sub, operator.mul, operator.div]

combos = list(itertools.product(funcs, repeat=2))

>>[(<function operator.add>, <function operator.add>),
 (<function operator.add>, <function operator.sub>),
 (<function operator.add>, <function operator.mul>),
 (<function operator.add>, <function operator.div>),
 (<function operator.sub>, <function operator.add>),
 (<function operator.sub>, <function operator.sub>),
 (<function operator.sub>, <function operator.mul>),
 (<function operator.sub>, <function operator.div>),
 (<function operator.mul>, <function operator.add>),
 (<function operator.mul>, <function operator.sub>),
 (<function operator.mul>, <function operator.mul>),
 (<function operator.mul>, <function operator.div>),
 (<function operator.div>, <function operator.add>),
 (<function operator.div>, <function operator.sub>),
 (<function operator.div>, <function operator.mul>),
 (<function operator.div>, <function operator.div>)]

      



We will then iterate over this list, solving all possible results:

for fn in combos:
    print 'This combo {} yielded this result {}'.format(fn, fn[1](fn[0](*seq[:2]), seq[-1]))

This combo (<built-in function add>, <built-in function add>) yielded this result 6
This combo (<built-in function add>, <built-in function sub>) yielded this result 0
This combo (<built-in function add>, <built-in function mul>) yielded this result 9
This combo (<built-in function add>, <built-in function div>) yielded this result 1
This combo (<built-in function sub>, <built-in function add>) yielded this result 2
This combo (<built-in function sub>, <built-in function sub>) yielded this result -4
This combo (<built-in function sub>, <built-in function mul>) yielded this result -3
This combo (<built-in function sub>, <built-in function div>) yielded this result -1
This combo (<built-in function mul>, <built-in function add>) yielded this result 5
This combo (<built-in function mul>, <built-in function sub>) yielded this result -1
This combo (<built-in function mul>, <built-in function mul>) yielded this result 6
This combo (<built-in function mul>, <built-in function div>) yielded this result 0
This combo (<built-in function div>, <built-in function add>) yielded this result 3
This combo (<built-in function div>, <built-in function sub>) yielded this result -3
This combo (<built-in function div>, <built-in function mul>) yielded this result 0
This combo (<built-in function div>, <built-in function div>) yielded this result 0

      

Edit: here is what follows the rules of operations

ops = ['+','-','*','/']

combos = list(itertools.product(ops, repeat=2))

for tup in list(itertools.product(combos, [seq])):
    print 'These operations {} evaluate to this ---> {}'.format(tup[0],eval(''.join(*zip(seq[0],tup[0][0],seq[1],tup[0][1],seq[-1]))))

These operations ('+', '+') evaluate to this ---> 6
These operations ('+', '-') evaluate to this ---> 0
These operations ('+', '*') evaluate to this ---> 7
These operations ('+', '/') evaluate to this ---> 1
These operations ('-', '+') evaluate to this ---> 2
These operations ('-', '-') evaluate to this ---> -4
These operations ('-', '*') evaluate to this ---> -5
These operations ('-', '/') evaluate to this ---> 1
These operations ('*', '+') evaluate to this ---> 5
These operations ('*', '-') evaluate to this ---> -1
These operations ('*', '*') evaluate to this ---> 6
These operations ('*', '/') evaluate to this ---> 0
These operations ('/', '+') evaluate to this ---> 3
These operations ('/', '-') evaluate to this ---> -3
These operations ('/', '*') evaluate to this ---> 0
These operations ('/', '/') evaluate to this ---> 0

      

+1


source


Not graceful (done on the knee) but works, just to point out my logic. The idea is to shorten the list one by one in the correct order. For example:.

Data: 1 * 2 + 3 * 4

  • After step 1 (first * estimated): 2 + 3 * 4
  • After step 2 (second * rated): 2 + 12
  • After step 3 (+ score): 14

Code:

import operator
import itertools

data = [1.0, 2.0, 3.0, 4.0]
operators_1 = [operator.mul, operator.div] # this operators have priority over that below
operators_2 = [operator.add, operator.sub]

def processOps(formula, data, operators):
    res_formula = list(formula)
    result = list(data)
    for op in formula:
        if op not in operators: continue

        i = res_formula.index(op)
        result = result[:i] + [op(result[i], result[i + 1])] + result[i + 2:]
        res_formula.remove(op)

        if len(result) == 1:
            break

    return (res_formula, result)

for f in itertools.product(operators_1 + operators_2, repeat=len(data)-1):
    result = list(data)
    formula = list(f)
    formula, result = processOps(formula, result, operators_1)
    formula, result = processOps(formula, result, operators_2)
    print f, result

      

UDP . This updated logic correctly handles cases like (1 * 2) + (3/4).

+1


source


Use the appropriate functions in the module operator

and iterate over them in pairs.

import itertools
import operator

ops = [operator.add, operator.sub, operator.mul, operator.div]

for f1, f2 in itertools.product(*ops, repeat=2):
    print f1(array[0], f2(array[1], array[2]))

      

Now, if it array

can be of arbitrary length, it gets a little trickier.

for operations in itertools.product(*ops, repeat=len(array)-1):
  result = operations[0](array[0], array[1])
  for op, operand in zip(operations[1:], array[2:]):
      result = op(result, operand)
  print(result)

      

The structure above avoids the need to know the appropriate identification element for each operation.

If you want to subordinate priority (as seems likely), you need to create an expression and evaluate it with eval

(standard warnings apply).

for ops in itertool.product("+", "-", "*", "/", repeat=len(array)-1):
  expr = "%s%s%s" % (array[0], ops[0], array[1])
  for op, operand in zip(ops[1:], array[2:]):
    expr = "%s%s%s" % (expr, op, operand)
  result = eval(expr)

      

I leave it as an exercise to extend this expression to create parenthesized expressions such as (1+2)*3

in addition to 1+2*3

.

0


source







All Articles