Calculate probability of dice total I am working on a project to get dice probability that requires 4 decimals places. My code works great, until the dice become huge (as I use in the example below). I am wondering if there is a way to make the process less laborious.
I should specify that I do already know that the choices list ending up so large is the performance issue.  I am looking for ways to improve performance.
An explanation of my code is:

We have \$n\$ dice each with \$f\$ faces and a target \$t\$. I want to know all the combinations of these dice to total \$t\$.
When: \$n = 2\$, \$f = 6\$ and \$t = 10\$, the following are the possible combinations:

4, 6
5, 5
6, 4

meaning poss_combinations returns \$3\$.

from itertools import product

dice = 10
faces = 10
number = 50

def poss_combinations(dice, faces, number):
    choices = list(product(range(1, faces+1), repeat=dice))
    count = 0
    for i in choices:
        if sum(i) == number:
            count += 1
    return count

answer = poss_combinations(dice, faces, number) / float(faces**dice)

return round(answer,4)
import

why import product within your method, and not in the module scope? 

instantiation

There is just no reason to instantiate the list in 

choices = list(product(range(1, faces+1), repeat=dice))


when you just iterate over it.

As noted by @JordanSinger, this takes a huge toll on memory, while using it as an iterable suffices



numpy alternative

a = sum(
    np.meshgrid(
        *(np.arange(1, faces + 1, dtype="uint8") for _ in range(dice)),
        copy=False
    )
)
(a == number).sum()


but for larger number of dice and faces this runs into MemoryError too

alternative

The integer value of True is 1. So instead of keeping a counter, and incrementing it each time there is a match, you can do:

def poss_combinations(dice, faces, number):
    choices = product(range(1, faces+1), repeat=dice)
    return sum(sum(roll) == number for roll in choices)


But even this will take ages for 10**10 combinations. Better would be to use a analytical formula like this one



alternative 2

A first alternative, is instead of taking the product, using itertools.combination_with_replacement to get all the combinations of dice rolls. For 10 10-faced dice, this is sum(1 for _ in combinations_with_replacement(range(10), 10)) or 92378. This is a much better number to work with that 10**10

The next step is to check which combinations combine to numbers, and then calculate how much of these combinations are possible link

from collections import Counter
from functools import reduce
from math import factorial
from operator import mul


def product_math(iterable):
    return reduce(mul, iterable, 1)


def combination_permutations(combination):
    c = Counter(combination)
    return factorial(sum(c.values())) / product_math(
        factorial(i) for i in c.values()
    )


calculates the number of possible permutations of a combination

def poss_comb_permutations(dice, faces, numbers):
    return sum(
        combination_permutations(combination)
        for combination in combinations_with_replacement(
            range(1, faces + 1), dice
        )
        if sum(combination) == numbers
    )


Then uses this to calculate the number of matching dice rolls.

All 3 methods arrive at the same result for 

dice = 7
faces = 7
number = 20