Skip to content
advent of code 2021

day 21

dirac dice

approach

part 1 is a straight simulation with a deterministic die: each turn rolls three consecutive numbers, moves around a 10-space track, and stops once someone reaches 1000.

part 2 splits the universe on every roll of a 3-sided die. three rolls only produce sums 3–9, with known frequencies (1, 3, 6, 7, 6, 3, 1 ways), so the solution recurses on (score1, score2, pos1, pos2, turn), multiplying each branch by how many universes reach it. lru_cache collapses the repeated states, and it returns win counts for both players as a vector.

the trick

roll the three dice together: 27 universes collapse into 7 outcomes with weights, and memoization does the rest.

python
for k, v in [(3,1),(4,3),(5,6),(6,7),(7,6),(8,3),(9,1)]:
    np = (p1 + k) % 10
    ns = s1 + np + 1
    s = s.add(dp(ns, s2, np, p2, 1).scale(v))