该解决方案应该可以工作-不确定您的系统需要多长时间。
from itertools import product
lg = (p for p in product(xrange(1,13,1),repeat=10) if sum(p) == 70)
results = {}
for l in lg:
results[l] = [p for p in product(xrange(1,min(l),1),repeat=10)]
它所做的是首先创建“前十名”。然后向每个“前十”添加一个可能的“下十”项目的列表,其中最大值被限制为“前十”中的最小项目
results 是一个字典,其中 thekey
是“前十个”,值是可能的“下一个十个”的列表
解决方案(符合要求的组合数量)将计算所有结果字典中的列表数量,如下所示:
count = 0
for k, v in results.items():
count += len(v)
然后count
将是结果。
更新
好的,我想到了一种更好的方法。
from itertools import product
import math
def calc_ways(dice, sides, top, total):
top_dice = (p for p in product(xrange(1,sides+1,1),repeat=top) if sum(p) == total)
n_count = dict((n, math.pow(n, dice-top)) for n in xrange(1,sides+1,1))
count = 0
for l in top_dice:
count += n_count[min(l)]
return count
因为我只计算“下一个十”的长度,所以我想我会预先计算“前十”中每个“最低”数字的选项数量,所以我创建了一个字典来做到这一点。上面的代码运行起来会更流畅,因为它只包含一个小字典、一个计数器和一个生成器。正如你可以想象的那样,它可能仍然需要很长时间......但我在不到 1 分钟的时间内运行了它以获得前 100 万个结果。所以我确信它在可行的范围内。
祝你好运 :)
更新 2
在你的另一条评论之后,我明白我做错了什么并试图纠正它。
from itertools import product, combinations_with_replacement, permutations
import math
def calc_ways(dice, sides, top, total):
top_dice = (p for p in product(xrange(1,sides+1,1),repeat=top) if sum(p) == total)
n_dice = dice-top
n_sets = len(set([p for p in permutations(range(n_dice)+['x']*top)]))
n_count = dict((n, n_sets*len([p for p in combinations_with_replacement(range(1,n+1,1),n_dice)])) for n in xrange(1,sides+1,1))
count = 0
for l in top_dice:
count += n_count[min(l)]
return count
正如你可以想象的那样,这是一场灾难,甚至没有给出正确的答案。我想我要把这个留给数学家。因为我解决这个问题的方法很简单:
def calc_ways1(dice, sides, top, total):
return len([p for p in product(xrange(1,sides+1,1),repeat=dice) if sum(sorted(p)[-top:]) == total])
这是一个优雅的 1 行解决方案,并提供了正确的答案,calc_ways1(5,6,3,15)
但需要永远解决这个calc_ways1(20,12,10,70)
问题。
无论如何,数学似乎是解决这个问题的方法,而不是我的愚蠢想法。