2

I'm willing to make a program that evaluates all possible combinations of operations ( + , - , * , / ) on a set of positive integers of length 6 (eg : [1, 6, 3, 9, 2, 9] ).

To do so, I am using the list

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

and wrote a nested loop to create all possibilities

+ + + + +
+ + + + -
.
.
.
/ / / / *
/ / / / /

by calling each row (eg : + - + * / ) a motif, and M the set of all motifs where

M[0] = ['+', '+', '+', '+', '+']
M[1] = ['+', '+', '+', '+', '-']

and so on. My goal now would be to write a function

evaluate_expression(motif, a, b, c, d, e, f)

that spits out the result of the expression a motif[0] b motif[1] c motif[2] d motif[3] e motif[4] f

my idea was to try converting '+' into the symbol + but I couldn't find a way to do it, I hope some of you guys here would know how to do that, I'm open to any suggestion of modification to make this cleaner.

Gautham M
  • 4,816
  • 3
  • 15
  • 37
Théo
  • 31
  • 3
  • Given the motif ``+ * + * +``, do you want to evaluate ``((((a + b) * c) + d) * e) + f`` or ``a + (b * c) + (d * e) + f``? – MisterMiyagi Feb 26 '21 at 12:27
  • Your question is similar to this one [here](https://stackoverflow.com/questions/2371436/evaluating-a-mathematical-expression-in-a-string) – MohammadHosseinZiyaaddini Feb 26 '21 at 12:31
  • can `eval` be used `[eval('1{}6{}3{}9{}2{}9'.format(*i)) for i in itertools.product(['+', '-', '*', '/'], repeat=5)]` ? – Epsi95 Feb 26 '21 at 12:41

4 Answers4

4

The operator library gives you functions for the basic operators (e.g. add(), sub())

So, you could replace your symbols = ['+', '-', '*', '/'] with:

from operator import add, sub, mul, truediv
symbols = [add, sub, mul, truediv]

and now your motif-generating function should make lists of functions instead of lists of strings.

Then, assuming you have a motif list, as you call it (check out itertools.combinations_with_replacement() for a function to generate all motifs), you can apply it by doing something like:

motif = [add, add, sub]
values = [5, 6, 7, 8]
 
result = values[0]
for i, current_func in enumerate(motif):
    result = current_func(result, value[i+1])

print(result)

Note: this method will not respect order of operations, it will apply the functions in order, left to right.

Zachary Cross
  • 2,298
  • 1
  • 15
  • 22
2

Using a Dictionary of function pointers seeems to be what you want to use.

from operator import add, sub, mul, truediv

operators = {
    '+': add,
    '-': sub,
    '*': mul,
    '/': truediv
}


def op(operator, a, b):
    return operators[operator](a, b)


print(op('+', 1, 2))
print(op('-', 1, 2))

In total, it could look like this:

from operator import add, sub, mul, truediv

operators = {
    '+': add,
    '-': sub,
    '*': mul,
    '/': truediv
}


def op(operator_list, param_list):
    assert len(operator_list)+1 == len(param_list)
    assert len(param_list) > 0
    res = param_list[0]
    for i in range(len(operator_list)):
        res = operators[operator_list[i]](res, param_list[i])
    return res


print(op(['+', '-'], [1, 2, 4]))
lennihein
  • 81
  • 5
-1

You can execute strings with eval("...").

def evaluate_expression(operands, operators):
    assert len(operands)==len(operators)+1
    expression = str(operands[0])
    for idx, operator in enumerate(operators):
        expression += str(operator)+str(operands[idx+1])
    return eval(expression)

The function can be called like this evaluate_expression([1,2,3,4,5],["+","-","+","-"]) and will calculate 1+2-3+4-5 = -1

haschtl
  • 89
  • 1
  • 7
  • did not downvote myself, but I can imagine that those who did didn't like the use of eval to cast strings to functions. It's a bit hacky, and given there are other ways to do it, your solution is not the recommended way. – lennihein Feb 28 '21 at 17:29
-1

I don't think there's a direct way to typecast a string to an operator (at least in the core python library) but what you could do is create the whole expression as a string and run eval() whiles passing it in.

opnd = [1, 6, 3, 9, 2]
oprt = ['+', '-', '*', '/']

def string_eval(operands,operators):
    final_string = ""
    for i in range(len(operands)):
        final_string += str(operands[i])
        if i < len(operators):
            final_string += str(operators[i])
    return eval(final_string)

print(string_eval(opnd,oprt))

Output -6.5

Hamzah Bawah
  • 11
  • 1
  • 4