trying all combinations of operations on list of variables
<p>I have a list of values like:</p>

<pre><code>values = [1, 2, 3, 4]
</code></pre>

<p>and I want to try all combinations on this list like:</p>

<pre><code>1 + 2
1 + 3
1 + 4
1 * 2
1 * 3
1 * 4
1 + 2 * 3
1 + 2 * 4
1 + 3 * 4
</code></pre>

<p>etc.</p>

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

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

<p>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?</p>

<p>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, <code>1 + 3 + 5 + 7</code>, would be <code>(((1 + 3) +5) + 7)</code>. 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.</p>

<p>I use itertools.</p>

<pre><code>from itertools import combinations_with_replacement
from itertools import permutations
from itertools import product
from itertools import chain
</code></pre>

<p>To display all expressions we call:</p>

<pre><code>def list_all(operations, values):
    if len(values) == 1:
        return values
    permutes = []
    ops = []
    expressions = []
    # for 4 values we want combinations with 2, 3 and 4 values.
    for subset in range(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
</code></pre>

<p>And to evaluate them, <code>execute</code> takes the output of <code>list_all</code>:</p>

<pre><code>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) &gt; 0:
            res = oplist.pop(0)(res, arglist.pop(0))
        results.append(res)
    return results
</code></pre>

<p>Example usage:</p>

<pre><code>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))
</code></pre>

python combinations