Problem 84 — Monopoly Odds

solved Fri, 18 Jul 2025, 23:01 · level 4 · difficulty 12% projecteuler.net github

In the game, Monopoly, the standard board is set up in the following way:

0084_monopoly_board.png

A player starts on the GO square and adds the scores on two 6-sided dice to determine the number of squares they advance in a clockwise direction. Without any further rules we would expect to visit each square with equal probability: 2.5%. However, landing on G2J (Go To Jail), CC (community chest), and CH (chance) changes this distribution.

In addition to G2J, and one card from each of CC and CH, that orders the player to go directly to jail, if a player rolls three consecutive doubles, they do not advance the result of their 3rd roll. Instead they proceed directly to jail.

At the beginning of the game, the CC and CH cards are shuffled. When a player lands on CC or CH they take a card from the top of the respective pile and, after following the instructions, it is returned to the bottom of the pile. There are sixteen cards in each pile, but for the purpose of this problem we are only concerned with cards that order a movement; any instruction not concerned with movement will be ignored and the player will remain on the CC/CH square.

  • Community Chest (2/16 cards):
    1. Advance to GO
    2. Go to JAIL
  • Chance (10/16 cards):
    1. Advance to GO
    2. Go to JAIL
    3. Go to C1
    4. Go to E3
    5. Go to H2
    6. Go to R1
    7. Go to next R (railway company)
    8. Go to next R
    9. Go to next U (utility company)
    10. Go back 3 squares.

The heart of this problem concerns the likelihood of visiting a particular square. That is, the probability of finishing at that square after a roll. For this reason it should be clear that, with the exception of G2J for which the probability of finishing on it is zero, the CH squares will have the lowest probabilities, as 5/8 request a movement to another square, and it is the final square that the player finishes at on each roll that we are interested in. We shall make no distinction between "Just Visiting" and being sent to JAIL, and we shall also ignore the rule about requiring a double to "get out of jail", assuming that they pay to get out on their next turn.

By starting at GO and numbering the squares sequentially from 00 to 39 we can concatenate these two-digit numbers to produce strings that correspond with sets of squares.

Statistically it can be shown that the three most popular squares, in order, are JAIL (6.24%) = Square 10, E3 (3.18%) = Square 24, and GO (3.09%) = Square 00. So these three most popular squares can be listed with the six-digit modal string: 102400.

If, instead of using two 6-sided dice, two 4-sided dice are used, find the six-digit modal string.


Problem Analysis

At its core this is a question about a Markov chain: a stochastic process whose next state depends only on the current state and a fixed set of transition probabilities, never on the full path taken to reach it. The board's 40 squares are the states, and one turn - a dice roll followed by any card or "Go To Jail" redirection - defines the transition rule. What the problem asks for is the stationary distribution: the long-run fraction of turns that finish on each square, which an ergodic chain converges to regardless of where it started. From that distribution I need only the three squares with the highest probability, concatenated as zero-padded indices.

The distribution is non-uniform because several mechanics redirect the player after the roll. G2J sends you straight to Jail; Community Chest (CC) and Chance (CH) draw cards that may move you elsewhere - Chance is the most disruptive, with 10 of its 16 cards commanding a move, several of them relative ("next railway", "next utility", "go back 3"). On top of that, rolling three consecutive doubles sends the player directly to Jail regardless of the roll. These coupled rules make the transition probabilities intricate, but they are all exactly computable - there is no need to approximate.

The natural temptation is a Monte Carlo simulation: roll a million dice and tally. The fatal flaw is that simulation is non-deterministic - the harness runs solve() several times and requires an identical result each time, but a random walk yields a slightly different modal string on every run, and with the leading squares often statistically close the ranking itself can flip. The exact approach has no such weakness: it computes the steady state directly, so the answer is reproducible to the last digit.

Solution Approach

Exact Stationary Distribution (Python and C)

Both files implement the same algorithm in three stages: build the transition matrix, power-iterate it to the stationary distribution, then marginalise and rank. The board is kept as an ordered list of 40 name strings rather than bare integers, so the rules read almost as a direct transcription: identifying a CC square is a "CC" prefix test, and "go to next railway" is "scan clockwise to the next name starting with R". Nothing depends on magic indices.

Resolving a Landing Square into Finishing Probabilities

The helper resolve(landing) returns the probability distribution over the squares a player can finish on, given the roll dropped them on landing. A plain square maps to itself with probability 1; G2J maps wholly to Jail. A CC square splits 2/16 onto its two movement cards (Advance to GO, Go to Jail) and 14/16 staying put. A CH square splits across its ten movement cards - the absolute targets (GO, Jail, C1, E3, H2, R1), the relative "next R" (which appears twice, giving 2/16) and "next U" found by a forward scan, and "go back 3" - with 6/16 staying put. One subtlety the simulation got wrong by omission: "go back 3" from CH3 (square 36) lands on CC3, which then triggers a Community Chest draw. resolve handles this by recursing on the back-3 destination and folding its distribution in, so the chained card is modelled exactly.

The Augmented State and the Three-Doubles Rule

A chain over the 40 squares alone cannot express "three consecutive doubles", because that depends on history. The fix is to augment the state with the number of consecutive doubles carried into the turn (0, 1 or 2), giving 120 states indexed square * 3 + doubles. The transition then enumerates every ordered dice pair: a third successive double routes straight to Jail and resets the streak; otherwise the player moves, the landing square is resolved into finishing probabilities, and the streak advances (or resets on a non-double). Any move that finishes in Jail also resets the streak. This captures the rule faithfully rather than waving it away as negligible.

Power Iteration and Ranking

The stationary distribution is found by power iteration: start from the uniform vector and repeatedly multiply by the transition matrix until the change between successive iterates falls below 1e-15. Because the chain is ergodic this converges quickly to the dominant eigenvector (eigenvalue 1). The 120-state distribution is then marginalised back to 40 per-square probabilities by summing over the doubles dimension, and the three largest are taken - with index as a deterministic tie-break - and formatted as the six-digit modal string. Both solutions reproduce the known 6-sided answer (102400) and yield 101524 for the 4-sided case.

workbench

Test cases

categoryinputanswer
dev dice_size = 6 102400
main dice_size = 4 101524

Results

solutioncategoryanswerverdict avg seconds cavg seconds py
p0084_s0 dev 102400 correct 0.002986 (105) 0.060643 (105)
p0084_s0 main 101524 correct 0.002855 (105) 0.065844 (105)

Files

Tags & blogs

Blogs