代码之家  ›  专栏  ›  技术社区  ›  Ashton Baker

骰子滚动笛卡尔积的嵌套计算

  •  0
  • Ashton Baker  · 技术社区  · 9 年前

    我正在开发一个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 回复  |  直到 9 年前
        1
  •  3
  •   Omega    9 年前

    正如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 用于文档

        2
  •  1
  •   Calum    9 年前

    你应该看看 itertools 特别关注组合和排列

        3
  •  1
  •   Bill Lynch    9 年前

    最简单的方法是使用 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)]
    

    如果我们想要可能的金额,我们可以通过 sum set :

    >>> 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] .