Один из способов значительно сократить время - это математически подсчитать, сколько комбинаций существует для каждой уникальной группы чисел в combinations
, и увеличить count
на эту величину.Если у вас есть список из n объектов, в которых все x1 одинаковы, x2 из них одинаковы и т. Д., То общее количество способов их размещения равно n! / (X1! X2! X3! ...),Например, количество различных способов расстановки букв «Теннесси» составляет 9! / (1! 4! 2! 2!).Таким образом, вы можете сделать отдельную функцию для этого:
import math
import itertools as it
import time
# Count the number of ways to arrange a list of items where
# some of the items may be identical.
def indiv_combos(thelist):
prod = math.factorial(len(thelist))
for i in set(thelist):
icount = thelist.count(i)
prod /= math.factorial(icount)
return prod
def final_count2(total, dice, faces):
combinations = it.combinations_with_replacement(range(1, faces + 1), dice)
count = 0
for i in combinations:
if sum(i) == total:
count += indiv_combos(i)
return count
Я не знаю, не знаю, есть ли уже какая-то встроенная функция, которая выполняет работу, которую я написал как indiv_combos2
, но выможно также использовать Counter
для подсчета и mul
для получения произведения из списка:
from operator import mul
from collections import Counter
def indiv_combos(thelist):
return math.factorial(len(thelist)) / reduce(mul, [math.factorial(i) for i in Counter(thelist).values()],1)
Я получаю смешанные результаты, когда пробую оба метода с (25, 10, 10)
в качестве ввода, но оба дают мне ответ менее чем за 0,038 секунды каждый раз.