2

I have the following:

a = [i/100 for i in range(5,105,5)]
a.append(0)
b = [i/100 for i in range(5,105,5)]
b.append(0)
c = [i/100 for i in range(5,105,5)]
c.append(0)
d = [i/100 for i in range(5,105,5)]
d.append(0)
e = [i/100 for i in range(5,105,5)]
e.append(0)

combs =  itertools.product(a,b,c,d,e)

'combs' would give me all possible combinations of a,b,c,d and e. However, I was wondering if I could combine them so that they add up to 1.

Thank you.

7
  • 5
    [comb for comb in combs if sum(comb) ==1] Commented Jan 17, 2017 at 18:32
  • 1
    @user3684792: although this works it would be rather inefficient don't you think? Commented Jan 17, 2017 at 18:33
  • list(filter(lambda x: sum(x) == 1, itertools.product(a,a,a,a,a))) Commented Jan 17, 2017 at 18:35
  • Is there are reason why you 1) repeat the same list comprehension for a, b, c, ... and 2) append zero to each? What are you trying to do? Commented Jan 17, 2017 at 18:37
  • @DPdl: do you know in advance you will only feed it positive values? Commented Jan 17, 2017 at 18:38

2 Answers 2

1

As far as I know there is no builtin way in to do this. You can evidently filter the result, but this would be rather inefficient: one expects only a small amount of combinations to add up to sum.

Given all fed values are positive (zero is acceptable) however, you can use this lazy function:

def product_sum(sum,*args):
    return product_sum_intern(sum,0,0,[],*args)

def product_sum_intern(sum,cur_sum,idx,cur,*args):
    if idx >= len(args):
        if sum == cur_sum:
            yield tuple(cur)
    elif cur_sum <= sum:
        for x in args[idx]:
            cur.append(x)
            for e in product_sum_intern(sum,cur_sum+x,idx+1,cur,*args):
                yield e
            cur.pop()

For instance:

>>> list(product_sum(15,[1,12],[1,4,7],[0,3,6,7],[0,1]))
[(1, 7, 6, 1), (1, 7, 7, 0)]

this algorithm gives up on branches as soon as it finds out it is already overshooting the sum. A more advanced algorithm exists that also gives up branches if there is no way to get in reach of the sum.

Sign up to request clarification or add additional context in comments.

1 Comment

Very efficient and perfect! Thank you @Willem Van Onsem.
0

To produce a list of all such results:

combs = [comb for comb in combs if sum(comb) ==1]

Or, if you can use a generator of that data:

combs = (comb for comb in combs if sum(comb) ==1)

1 Comment

I believe @user3684792 23 gave this answer

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.