Dice Simulation, Probabilities and Matplotlib Animations

Dice Simulation, Probabilities and Matplotlib Animations

Colab Notebook for Dice Rolling Simulations

Hi again! Last time, I worked with JavaScript. Now, it's time to bring out the king when we talk about programming languages for data analysis: Python. This weekend, I prepared this Google Colab notebook (Python Jupyter notebook-like environment in the cloud) mainly with the purpose of training my skills in plotting, and this time, animating with the Matplotlib library.

The idea is simple: create plots that, in each iteration, throw the dice randomly and add the sum of the numbers to the frequency bars. At the same time, a normal distribution line is drawn to compare the data with the probability prediction.

Here is the two-dice rolling simulation gif

Obviously, if I wanted to make just this two-dice simulation, it wouldn't be a problem. But my idea was to make a script capable of creating this kind of graph for any number of dice. Also, I achieved that multiple plots were rendered in the same figure to compare results.

To make this, I used a complete OOP system with around 150 lines of code to finally run the program with these simple lines:

# SAMPLE
builder = DiceSumPlotBuilder( [1,2] )
anim = builder.build( frames=50 )

In this case, you have to instantiate the DiceSumPlotBuilder class with a list of the number of dice you want to simulate. Then, the build method returns the Matplotliblib FuncAnimation object to render later.

When I believed I finished the project, I wondered what would happen if I tried the one-dice simulation and that didn't work with the normal distribution. I thought to draw a line with the same probability for the 6 cases, and I made it. A funny fact is that I spent around 10 minutes trying to see it, but I put the line with 50% for each one, and that was drawn outside the plot. Then I changed it to 16.66%, and all was fine. Here is the result:

This time I will share with you the complete Google Colab notebook, so you can try and upgrade it. But here, I share with you a block of code that calculates the probability of each possible result with a given number of dice.

def calculate_sum_probs( n_dices ):
  res = {}
  total_cases = 6 ** n_dices

  def genereate_sums( current_dice, acc ):
    if current_dice == 0:
        if not acc in res:
          res[acc] = 0
        res[acc] += 1
    else:
        for i in range(1,7):
          genereate_sums( current_dice - 1, acc + i)

  genereate_sums( n_dices, 0)
  probs = { sum: round(freq / total_cases,3) for sum, freq in res.items() }
  return probs

With this little recursive function, I was able to calculate the results with greater probability and the range of the simulation to fit the normal distribution.

Finally, I share with you the simulation of three, four, and five dice with 500 iterations (two-minute render time :) ) so you can enjoy the math as much as I. See you!

Google Colab Notebook