это решение должно работать - не уверен, сколько времени это займет в вашей системе.
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)]
что он делает, так это создает первую десятку. затем добавляет к каждой «десятке» список возможных «следующих десяти» элементов, где максимальное значение ограничено минимальным элементом в «десятке лучших»
результаты - это словарь, где key
- это "десятка лучших", а значение - список возможных "следующих десяти"
решение (количество комбинаций, соответствующих требованиям) состояло бы в том, чтобы подсчитать количество списков во всех результирующих словарях следующим образом:
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 минуту. поэтому я уверен, что это в допустимом диапазоне.
удачи :)
обновление 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])
которое представляет собой элегантное однострочное решение и дает правильный ответ для calc_ways1(5,6,3,15)
, но требует вечности для проблемы calc_ways1(20,12,10,70)
.
в любом случае, математика, похоже, подходит для этого, а не мои глупые идеи.
person
Inbar Rose
schedule
12.12.2012