Вложенное вычисление декартова произведения бросков костей

Я работаю над программой 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

Что происходит?


person Ashton Baker    schedule 12.03.2015    source источник
comment
@ mkrieger1 эта ссылка выглядит совершенно неуместной?   -  person smci    schedule 12.03.2015
comment
@AshtonBaker, который называется декартовым продуктом.   -  person smci    schedule 12.03.2015
comment
@smci спасибо, я должен был это признать.   -  person Ashton Baker    schedule 12.03.2015
comment
Не беспокойся. Я тоже это забываю   -  person smci    schedule 12.03.2015
comment
упс, я хотел связать этот вопрос (удаленный исходный комментарий)   -  person mkrieger1    schedule 12.03.2015


Ответы (3)


Как заметил Калум, вы должны использовать встроенные инструменты itertools для этих общих циклов.

В вашем случае вам нужно:

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

диапазон (1,5) представляет 4 стороны кубика

repeat = 9 представляет 9 кубиков, которые вы хотите бросить

См. Документ itertools.product.

person Omega    schedule 12.03.2015

вам следует взглянуть на itertools, обращая особое внимание на комбинации и перестановки

person Calum    schedule 12.03.2015

Самый простой способ - использовать модуль 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].

person Bill Lynch    schedule 12.03.2015