简体   繁体   中英

Summing combinations for the elements of a list with a constraint

I have a nested list g=[[2, 1],[1, 3],[8, 1]] . I want to have a list in which:

every inner element of the list added up to at most another two inner elements. Here's the process and therefore desired output:

# 1= a single element like g[0][1]
# 2= a single element like g[0][0] or can be added by two inner elements like g[0][1]+g[1][0]
# 3= a single g[1][1], adding two elements g[0][0]+g[1][0] or at most three g[0][1]+g[1][0]+g[2][1] 
.
.
.
# 13= g[0][0]+g[1][1]+g[2][0]

So the final result will be a list. Notice there can't be 7 in the results since there's no combination (without replacement) that can be add up to 7. Also from each element at most one inner value can be selected.

expected_result = [1,2,3,4,5,6,8,9,10,11,12,13]

This is what I've done but it doesn't contain 1 and 2 and it also contains 7:

g=[[2, 1],[1, 3],[8, 1]]
from itertools import product
maxx = []
# Getting all possible combination of adding at most 3 elements (=length of g)
for i in list((product([i for j in g for i in j], repeat=len(g)))):
    maxx.append(sum(i))
    # Narrowing the result so it doesn't exceed the maximum combination which is sum([2,3,8])
print([i for i in set(maxx) if i<=sum(max_list)])

>>> [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

Any help is appreciated.

It seems like the shape/format of the data is a red herring. Just flatten the list and looks for the unique sums of each combination of 1, 2, or 3 elements of the flattened list. Use itertools.chain to flatten the list, itertools.combinations to create the combinations, itertools.chain again to combine the combinations, and a set to return unique results:

>>> import itertools
>>> g = [[2, 1],[1, 3],[8, 1]]
>>> flattened = itertools.chain(*g)
>>> flattened
[2, 1, 1, 3, 8, 1]
>>> list(set(map(sum,
  itertools.chain(itertools.combinations(flattened, 1), 
                  itertools.combinations(flattened, 2),
                  itertools.combinations(flattened, 3)))))
[1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13]

Edit : The question was changed to include the following constraint:

Also from each element at most one inner value can be selected.

That means you can't flatten the list. Here's an updated solution that satisfies the new constraint:

>>> list(set(map(sum,
        itertools.chain.from_iterable(itertools.combinations(p, n)
        for n in range(1,4)
        for p in itertools.product(*g)))))
[1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13]

>>> g = [[2, 1],[1, 3],[8, 1],[14, 15]  # should not produce 29 as an answer
>>> list(set(map(sum,
        itertools.chain.from_iterable(itertools.combinations(p, n)
        for n in range(1,4)
        for p in itertools.product(*g)))))
[1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26]

The simpliest implementation that I can think of now:

def fun(numbers):
    all_numbers = [x for y in numbers for x in y]
    output = list(set(all_numbers))
    for x in all_numbers:
        for y in all_numbers:
            if x is not y:
                output.append(x + y)
            for z in all_numbers:
                if y is not x and y is not z and x is not z:
                    output.append(x + y + z)
    return list(set(output))


print(fun([[2, 1], [1, 3], [8, 1]]))

Above code prints

[1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM