嵌套计算骰子卷的笛卡尔积

时间:2015-03-12 00:38:43

标签: python permutation itertools dice cartesian-product

我正在开发一个Python程序,我必须想出所有方法来滚动9个4面骰子。我一直试图想出一个更简洁的方式来写这一行:

for n in [sum([a, b, c, d, e, f, g, h, i]) for a in range(1, 5) for b in range(1, 5) for c in range(1, 5) for d in range(1, 5) for e in range(1, 5) for f in range(1, 5) for g in range(1, 5) for h in range(1, 5) for i in range(1, 5)]:

我见过类似的语法:

for n in [sum([a, b, c, d, e, f, g, h, i]) for a, b, c, d, e, f, g, h, i in range(1, 5)]:

但这会产生错误:

TypeError: 'int' object is not iterable

发生了什么事?

3 个答案:

答案 0 :(得分:3)

正如Calum所说,你应该使用内置的itertools来实现这些常见的循环。

在您的情况下,您需要:

import itertools
results = [sum(x) for x in itertools.product(range(1,5),repeat=9)]

范围(1,5)代表模具的4个边

repeat = 9代表你要掷骰子的9个骰子

请参阅itertools.product了解文档

答案 1 :(得分:1)

你应该专注于itertools看看组合和排列

答案 2 :(得分:1)

最简单的方法是使用itertools模块。所以在你的特定情况下,我们可以这样做:

import itertools
itertools.combinations_with_replacement(range(1, 5), 9))

哪会生产发电机。如果我们迭代它,我们会看到它包含:

[(1, 1, 1, 1, 1, 1, 1, 1, 1),
 (1, 1, 1, 1, 1, 1, 1, 1, 2),
 (1, 1, 1, 1, 1, 1, 1, 1, 3),
 (1, 1, 1, 1, 1, 1, 1, 1, 4),
 (1, 1, 1, 1, 1, 1, 1, 2, 2),
 (1, 1, 1, 1, 1, 1, 1, 2, 3),
 ...
 (3, 3, 4, 4, 4, 4, 4, 4, 4),
 (3, 4, 4, 4, 4, 4, 4, 4, 4),
 (4, 4, 4, 4, 4, 4, 4, 4, 4)]

如果我们想要可能的总和,我们可以通过sumset轻松扩展这一点:

>>> set(sum(dice) for dice in itertools.combinations_with_replacement(range(1, 7), 9))
set([9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54])

但我们也知道(通过数学!)范围将是[1*9, 4*9]的封闭集。