简体   繁体   English

有没有一种有效的方法可以找到所有长度为 10 的 integer 元组总和为 100

[英]Is there an efficient way to find all integer tuples of length 10 that sum to 100

I am trying to find all tuples containing only positive integers (0 allowed) that add to 100. I have some constraints on the max values for each index.我正在尝试查找仅包含加到 100 的正整数(允许为 0)的所有元组。我对每个索引的最大值有一些限制。 I have the list maxs that include these constraints我有包含这些约束的列表最大值

maxs = [3, 9, 14, 21, 21, 35, 31, 49, 42, 38]

So far I am simply running this 10 dimensional nested for loop到目前为止,我只是在运行这个 10 维嵌套 for 循环

combinations = []
for s1 in range(maxs[0]+1):
    for s2 in range(maxs[1]+1):
        for s3 in range(maxs[2]+1):
            for s4 in range(maxs[3]+1):
                for s5 in range(maxs[4]+1):
                    for s6 in range(maxs[5]+1):
                        for s7 in range(maxs[6]+1):
                            for s8 in range(maxs[7]+1):
                                for s9 in range(maxs[8]+1):
                                    for s10 in range(maxs[9]+1):
                                        if s1 +s2+s3+s4+s5+s6+s7+s8+s9+s10 == 100:
                                            combinations.append([s1,s2,s3,s4,s5,s6,s7,s8,s9,s10]

I know there are stictly less than 10^11 combinations if that helps at all.如果有帮助的话,我知道只有不到 10 ^ 11 种组合。 Maybe this problem is too large可能这个问题太大了

Thanks谢谢

This one is not the best performant one, but it is the easiest.这不是性能最好的,但它是最简单的。

from itertools import combinations

maxs = [3, 9, 14, 21, 21, 35, 31, 49, 42, 38]

combination = [
    tuple(filter(lambda x: 0 <= x <= 100, item))
    for r in range(1, len(maxs))
    for item in combinations(maxs, r)
]
result = [item for item in combination if sum(item) == 100]

print(result)

Recursive approach.递归方法。 Example uses only three first entries.示例仅使用三个第一个条目。 Acceleration is possible with early bad branch cutting - for example, when cursum exceeds target早期的不良分支切割可能会加速 - 例如,当 cursum 超过目标时

maxs = [3, 9, 14, 21, 21, 35, 31, 49, 42, 38]

def sum100(n, target, maxs, level, cursum, curlist):
    if level == n:
        if cursum == target:
            print(curlist)
        return
    for i in range(maxs[level]+1):
        sum100(n, target, maxs, level + 1, cursum + i, curlist + [i])

sum100(3, 15, maxs, 0, 0, [])

[0, 1, 14]
[0, 2, 13]
...
[1, 3, 11]
[1, 4, 10]
[1, 5, 9]
...
[3, 1, 11]
[3, 2, 10]
[3, 3, 9]

I know that there is an accepted solution.我知道有一个公认的解决方案。

But here is one that allows you to solve a variety of problems like this.但这里有一个可以让你解决这样的各种问题。 It allows you to count solutions, produce solutions in lexicographic order, or produce any random solution.它允许您计算解决方案,按字典顺序生成解决方案,或生成任何随机解决方案。 It does that by using dynamic programming to build a structure for all solutions, from which you can do with it as you want.它通过使用动态编程为所有解决方案构建结构来做到这一点,您可以根据需要使用它。

Here is a demonstration:这是一个演示:

import random

def summer (target, choices_list, i=0, cache=None):
    if cache is None:
        cache = {}
    key = (target, i)
    if key not in cache:
        if i == len(choices_list):
            if target == 0:
                cache[key] = {0: [1, None]}
            else:
                cache[key] = None
        elif len(choices_list) < i:
            cache[key] = None
        else:
            answer = {}
            for choice in choices_list[i]:
                next_target = target - choice
                next_summer = summer(next_target, choices_list, i+1, cache)
                if next_summer is not None:
                    count = sum([v[0] for v in next_summer.values()])
                    answer[choice] = [count, next_summer]
            if 0 == len(answer.keys()):
                cache[key] = None
            else:
                cache[key] = answer

    return cache[key]

def max_summer(target, maxes):
    return summer(target, [list(range(0, m+1)) for m in maxes])

def count_solutions(this_summer):
    if this_summer is None:
        return 0
    else:
        answer = 0
        for v in this_summer.values():
            answer += v[0]
        return answer

def solution (this_summer, i, answer = None):
    if answer is None:
        answer = []

    if this_summer is None:
        answer.pop() # Remove trailing 0
        return answer

    for choice, info in this_summer.items():
        if info[0] < i:
            i -= info[0]
        else:
            answer.append(choice)
            return solution(info[1], i, answer)

    return None


s = max_summer(100, [3, 9, 14, 21, 21, 35, 31, 49, 42, 38])
print(count_solutions(s))

for x in range(10):
    i = x
    print(i, solution(s, i))

for x in range(10):
    i = random.randrange(0, count_solutions(s))
    print(i, solution(s, i))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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