簡體   English   中英

查找唯一求和為一組數字的所有數字組合

[英]Find All Combinations of Numbers That Uniquely Sum to a Set of Numbers

我有一個數字列表(源集),有人拿走了部分或全部這些數字,然后將它們隨機求和,以得出較小的一組數字(目標集)。 我有源集和目標集,但是我需要弄清楚使用了哪種組合。 難度:我不能保證將源集中的所有數字都用作目標集,也不能保證目標集中的所有數字都來自源集合。 這是一個簡單的例子:

  • 源集= 1,2,3,4,5
  • 目標設定= 3,8
  • 結果:
    • ResultSet1:Sum([1,2])= 3 Sum([3,5])= 8 NotFound([])NotUsed([4])
    • ResultSet2:Sum([3])= 3 Sum([1,2,5])= 8 NotFound([])NotUsed([4])
    • ResultSet3:Sum([1,3,4])= 8 NotFound([3])NotUsed([2,5])
  • 無效的答案:
    • InvalidSet1:Sum([1,2])= 3 Sum([3])= 3 Sum([3,5])= 8 NotFound([])未使用:[4]
      • 原因:源集中的每個數字只能用於一次在給定結果集中創建任何目標

我已經找到了一些很好的示例,可以在給定單個目標值的情況下推導上述值,但是我找不到一種方法來對目標值數組(而不是單個值)進行處理(很遺憾,我的編碼技能無法勝任該任務)。 我最好的開始就是這個問題 ,下面的代碼(請注意,我刪除了s> = target檢查以容納我的數據):

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([1,2,3,4,5],4)

這將輸出:

sum([1, 3])=4
sum([4])=4

我已經做了一些英勇的嘗試,添加了第二層遞歸以支持目標數組,但是我不會因為失敗而感到尷尬。

我知道上面的代碼有局限性,並且我願意接受基於此代碼或全新代碼的解決方案,並以幾乎任何邏輯格式輸出。 強烈推薦使用Python,但是我幾乎會接受所有事情(請注意:java給了我蕁麻疹)。

您的意思是:

In []:
import itertools as it

source = [1, 2, 3, 4, 5]
targets = [3, 8]

p = [[a for n in range(1, len(source)) for a in it.combinations(source, n) if sum(a) == t] for t in targets]
[dict(zip(targets, a)) for a in it.product(*p) if len(sum(a, tuple())) == len(set(sum(a, tuple())))]

Out[]:
[{3: (3,), 8: (1, 2, 5)}, {3: (1, 2), 8: (3, 5)}]

我發現的唯一方法是效率很低,而且我敢肯定必須有一種更聰明的方法,但是它可以工作。

想法是獲取所有組合,獲取第一個數字的組合,遍歷所有組合,從列表中刪除使用的數字,生成所有組合,獲取與第二個數字匹配的組合並進行迭代。

這是代碼。 同樣,這很丑陋,但確實可以做到:

from collections import defaultdict
import itertools as it

def get_all_combinations(l):
    return [a for n in range(1, len(l)) for a in it.combinations(l, n)]

def get_combinations_for_target(combinations, target):
    if combinations is None:
        return []
    return [combination for combination in combinations if sum(combination) == target]

def get_list_without_used_numbers(l, combination):
    used_numbers = []
    for item in combination:
        used_numbers.append(item)

    diff_list = list(set(l) - set(used_numbers))
    return diff_list

source = [1, 2, 3, 4, 5]
combinations = get_all_combinations(source)
combinations_first =  get_combinations_for_target(combinations, 3)

combinations_both = defaultdict(dict)

for combination in combinations_first:
    partial_list = get_list_without_used_numbers(source, combination)
    partial_combinations = get_all_combinations(partial_list)
    combinations_both[combination] = get_combinations_for_target(partial_combinations, 8)

print(combinations_both)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM