Add up the array of frequency of previous rolls, 'side number' times by shifting it's position, then you will get the array of frequencies each numbers show up.
1, 1, 1, 1, 1, 1 # 6 sides, 1 roll
1, 1, 1, 1, 1, 1
1, 1, 1, 1, 1, 1
1, 1, 1, 1, 1, 1
1, 1, 1, 1, 1, 1
1, 1, 1, 1, 1, 1
+ 1, 1, 1, 1, 1, 1
_______________________________
1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1 # 6 sides, 2 rolls
1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1
1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1
1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1
1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1
1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1
+ 1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1
______________________________________________
1, 3, 6,10,15,21,25,27,27,25,21,15,10, 6, 3, 1 # 6 sides, 3 rolls
This is much faster than brute force simulation, since simple equation is the best.
Here is my python3 implementation.
def dice_frequency(sides:int, rolls:int) -> list:
if rolls == 1:
return [1]*sides
prev = dice_frequency(sides, rolls-1)
return [sum(prev[i-j] for j in range(sides) if 0 <= i-j < len(prev))
for i in range(rolls*(sides-1)+1)]
for example,
dice_frequency(6,1) == [1, 1, 1, 1, 1, 1]
dice_frequency(6,2) == [1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1]
dice_frequency(6,3) == [1, 3, 6, 10, 15, 21, 25, 27, 27, 25, 21, 15, 10, 6, 3, 1]
Note that, you should use 'target number - roll count' as index of the list to get frequency of each number. If you want to get probabilities, use 'side number'^'roll count' as a denominator.
sides = 6
rolls = 3
freq = dice_frequency(sides,rolls)
freq_sum = sides**rolls
for target in range(rolls,rolls*sides+1):
index = target-rolls
if 0 <= index < len(freq):
print("%2d : %2d, %f" % (target, freq[index], freq[index]/freq_sum))
else:
print("%2d : %2d, %f" % (target, 0, 0.0))
This code yeilds
3 : 1, 0.004630
4 : 3, 0.013889
5 : 6, 0.027778
6 : 10, 0.046296
7 : 15, 0.069444
8 : 21, 0.097222
9 : 25, 0.115741
10 : 27, 0.125000
11 : 27, 0.125000
12 : 25, 0.115741
13 : 21, 0.097222
14 : 15, 0.069444
15 : 10, 0.046296
16 : 6, 0.027778
17 : 3, 0.013889
18 : 1, 0.004630