Skip to content

04-04: Probability Simulator

Statistics & Probability

View the live site — ijk37.com

Project 04

Home  |  All Projects  |  Notes  |  Exercises  |  Quiz Hub

Compute probabilities two ways — theoretically from the sample space, and empirically by simulation — and watch them converge. Covers the addition and multiplication rules, conditional probability, Bayes' theorem, and counting.

Chapters applied: 05-01 · 05-02 · 05-03

Difficulty: ⭐⭐ Beginner–Intermediate


The Data

data/dice_rolls.csv — 1,000 simulated rolls of two dice (trial, die1, die2, sum), so the empirical side has a fixed, reproducible data set to work from.

Everything else in this project is generated on the fly.


What You Produce

  1. The exact distribution of the sum of two dice (all 36 outcomes), with theoretical probabilities
  2. The empirical distribution from the 1,000 rolls, side by side with the theory
  3. A Law of Large Numbers convergence plot
  4. A contingency table with every marginal, joint, and conditional probability, plus an independence check
  5. A Bayes calculator for medical screening, showing how the answer moves with the base rate
  6. A counting section: permutations, combinations, lottery odds, and the birthday problem
  7. Optional: a Monty Hall simulation

Excel Route

Step 1 — The exact two-dice distribution

Put the sums 2…12 in H2:H12, then:

' number of ways to make each sum, from the 6x6 grid
=SUMPRODUCT((SEQUENCE(6)+TRANSPOSE(SEQUENCE(6))=H2)*1)      ' I2: ways
=I2/36                                                       ' J2: theoretical P
=SUM($J$2:J2)                                                ' K2: cumulative P

Check: SUM(I2:I12) must be 36 and SUM(J2:J12) must be 1.

Pre-365 alternative: build the full 6 × 6 grid of sums in B2:G7 with =$A2+B$1, then =COUNTIF($B$2:$G$7, H2)/36.

Step 2 — Empirical from the data

=COUNTIF($D$2:$D$1001, H2)/1000                  ' L2: empirical P
=L2-J2                                            ' M2: difference
=MAX(ABS(M2:M12))                                 ' largest gap — should be small

Chart both J and L as clustered columns to see the agreement.

Step 3 — Convergence (Law of Large Numbers)

=IF(D2=7,1,0)                                     ' N2: indicator, fill down
=SUM($N$2:N2)/ROW()-1                             ' O2: running proportion

Insert ▸ Line chart of column O, then add a horizontal line at 6/36 = 0.1667. The running estimate wanders wildly for the first 100 rolls and settles by 1,000.

Step 4 — Live simulation

=RANDBETWEEN(1,6)+RANDBETWEEN(1,6)                ' one roll; fill down 1,000 rows
=COUNTIF(range, 7)/1000                           ' press F9 to re-randomize

Turn off automatic recalculation while you read the results: Formulas ▸ Calculation Options ▸ Manual.

Step 5 — Contingency table

Build this 2 × 3 table of 200 survey responses:

Excellent Good Poor Total
Exercises 45 55 20 120
Does not 15 30 35 80
Total 60 85 55 200
=B2/$E$4                     ' joint        P(Exercises and Excellent) -> 0.225
=E2/$E$4                     ' marginal     P(Exercises)               -> 0.600
=B4/$E$4                     ' marginal     P(Excellent)               -> 0.300
=B2/$E2                      ' conditional  P(Excellent | Exercises)   -> 0.375
=B2/B$4                      ' conditional  P(Exercises | Excellent)   -> 0.750
=E2/$E$4+B4/$E$4-B2/$E$4     ' union        P(Exercises or Excellent)  -> 0.675
=E2*B4/$E$4                  ' expected if independent                 -> 36
=ROUND(B2/$E2,4)=ROUND(B4/$E$4,4)     ' TRUE only if independent -> FALSE

Step 6 — Bayes

' B1 = prevalence, B2 = sensitivity, B3 = false-positive rate
=B2*B1+B3*(1-B1)                        ' P(positive)
=B2*B1/(B2*B1+B3*(1-B1))                ' P(disease | positive)

' Natural-frequency version — the version people actually believe:
=10000*B1                               ' with disease
=10000*B1*B2                            ' true positives
=10000*(1-B1)*B3                        ' false positives
=B7/(B7+B8)                             ' same posterior, from counts

' Build a one-way Data Table over prevalence 0.001 … 0.50 and chart it:
'   Data ▸ What-If Analysis ▸ Data Table

Step 7 — Counting

=FACT(5)                                ' 120
=PERMUT(10,3)                           ' 720   order matters
=COMBIN(10,3)                           ' 120   order does not
=COMBIN(49,6)                           ' 13,983,816 lottery combinations
=1/COMBIN(49,6)                         ' jackpot probability
=COMBIN(6,5)*COMBIN(43,1)/COMBIN(49,6)  ' P(match exactly 5)
=MULTINOMIAL(1,4,4,2)                   ' MISSISSIPPI -> 34,650
=1-PRODUCT((365-SEQUENCE(23,,0,1))/365) ' birthday problem, k = 23 -> 0.5073

R Route

Rscript r/analysis.R

Runs every section above plus a Monty Hall simulation, and writes probability_plots.png. See r/analysis.R.

Python Route

python python/analysis.py

Same, via NumPy + pandas. See python/analysis.py.


Checkpoints

  • Theoretical probabilities sum to exactly 1
  • Empirical and theoretical distributions agree to within roughly ±0.02 at n = 1,000
  • The convergence plot shows wild early swings settling toward 1/6
  • P(A|B) and P(B|A) are computed and shown to differ
  • The independence check is done by comparing observed with expected counts
  • The Bayes result is presented both as a formula and as natural frequencies

Extend It

  • Simulate with 100, 1,000, 10,000 and 100,000 rolls and tabulate the maximum error against theory. Does it shrink like 1/√n?
  • Simulate three dice and derive the distribution of the sum
  • Add the "at least one 6 in four rolls" vs. "at least one double-six in 24 rolls" problem (de Méré's paradox)
  • Extend the Bayes section to a second test: what is the posterior after two independent positives?