web-dev-qa-db-ja.com

与えられた合計を持つ数のリストのすべての組み合わせを見つける

数字のリストがあります。

numbers = [1, 2, 3, 7, 7, 9, 10]

ご覧のとおり、このリストに数字が複数回表示される場合があります。

与えられた合計を持つこれらの数値のすべての組み合わせを取得する必要があります。 10

組み合わせのアイテムは繰り返されないかもしれませんが、numbersの各アイテムは一意に扱われる必要があります。リスト内の2つの7は、同じ値を持つ異なるアイテムを表します。

順序は重要ではないため、[1, 9][9, 1]は同じ組み合わせです。

組み合わせには長さの制限はありません。[10][1, 2, 7]と同じくらい有効です。

上記の条件を満たすすべての組み合わせのリストを作成するにはどうすればよいですか?

この例では、[[1,2,7], [1,2,7], [1,9], [3,7], [3,7], [10]]になります

10
Byte Commander

Itertoolsを使用して、考えられるすべてのサイズのあらゆる組み合わせを反復処理し、合計が10にならないものをすべて除外できます。

import itertools
numbers = [1, 2, 3, 7, 7, 9, 10]
result = [seq for i in range(len(numbers), 0, -1) for seq in itertools.combinations(numbers, i) if sum(seq) == 10]
print result

結果:

[(1, 2, 7), (1, 2, 7), (1, 9), (3, 7), (3, 7), (10,)]

残念ながら、これはO(2 ^ N)の複雑さのようなものであるため、たとえば20要素を超える入力リストには適していません。

16
Kevin

@ kgoodrickが提供するソリューション は素晴らしいですが、ジェネレータとしてより便利だと思います:

_def subset_sum(numbers, target, partial=[], partial_sum=0):
    if partial_sum == target:
        yield partial
    if partial_sum >= target:
        return
    for i, n in enumerate(numbers):
        remaining = numbers[i + 1:]
        yield from subset_sum(remaining, target, partial + [n], partial_sum + n)
_

list(subset_sum([1, 2, 3, 7, 7, 9, 10], 10))は_[[1, 2, 7], [1, 2, 7], [1, 9], [3, 7], [3, 7], [10]]_を生成します。

11
Martin Valgur

この質問は以前に尋ねられました。@ msalvadoresの回答 here を参照してください。 pythonで実行するように指定されたpythonコードを更新しました3:

def subset_sum(numbers, target, partial=[]):
    s = sum(partial)

    # check if the partial sum is equals to target
    if s == target:
        print("sum(%s)=%s" % (partial, target))
    if s >= target:
        return  # if we reach the number why bother to continue

    for i in range(len(numbers)):
        n = numbers[i]
        remaining = numbers[i + 1:]
        subset_sum(remaining, target, partial + [n])


if __name__ == "__main__":
    subset_sum([3, 3, 9, 8, 4, 5, 7, 10], 15)

    # Outputs:
    # sum([3, 8, 4])=15
    # sum([3, 5, 7])=15
    # sum([8, 7])=15
    # sum([5, 10])=15
7
kgoodrick

これは動作します...

from itertools import combinations


def SumTheList(thelist, target):
    arr = []
    p = []    
    if len(thelist) > 0:
        for r in range(0,len(thelist)+1):        
            arr += list(combinations(thelist, r))

        for item in arr:        
            if sum(item) == target:
                p.append(item)

    return p
0
MarsNebulaSoup