Books · The Fiddler: Solutions
Chapter 30
The Randy Hall Problem
A game show has three doors in a row, , , . A contestant starts at one door and presses a button many times; each press either keeps them put or moves them to an adjacent door. From door , a move goes to or with equal chance, and the host fixes a percent chance of staying at door . You want each door to be almost equally likely after many presses. What stay probability should the button give at door (and door )?
The Fiddler, Zach Wissner-Gross, November 7, 2025(original post)
Solution
Call the stay probability at doors and by . We want the long-run distribution to be uniform, at each door. The only ways to arrive at door are to stay there (probability ) or to step in from door or door (each leaving with probability ). Balance at door with every door at , so and
The computation
Build the transition matrix for and read off its stationary distribution (the left eigenvector for eigenvalue ). It is uniform, at every door.
import numpy as np
p = 0.6
M = np.array([[p, 1-p, 0], [0.4, 0.2, 0.4], [0, 1-p, p]]) # rows sum to 1
w, v = np.linalg.eig(M.T); s = np.real(v[:, np.argmin(abs(w-1))])
print(np.round(s/s.sum(), 4)) # [0.3333 0.3333 0.3333]
Extra Credit
Now door ’s stay probability alternates: percent on the odd presses, percent on the even ones. What stay probability at doors and makes the doors equally likely in the long run?
Solution
The walk now has period two, so its distribution oscillates; we ask that the time-average be uniform. Writing the door- probability after an odd and an even press in terms of and averaging, the uniform condition reduces to a quadratic, The alternating stickiness at door pushes the required stay probability up from to about . (The source’s value is behind its paywall; this is my own.)
The computation
Compose the two alternating press-matrices into one two-step cycle, take its stationary distribution, average over the odd and even half-steps, and solve for the that levels doors and .
from scipy.optimize import brentq
def avg_pi(p):
Mo = np.array([[p, 1-p, 0], [0.4, 0.2, 0.4], [0, 1-p, p]]) # odd press
Me = np.array([[p, 1-p, 0], [0.25, 0.5, 0.25], [0, 1-p, p]]) # even press
w, v = np.linalg.eig((Mo@Me).T); po = np.real(v[:, np.argmin(abs(w-1))]); po /= po.sum()
return (po + po@Mo)/2
p = brentq(lambda p: avg_pi(p)[0] - avg_pi(p)[1], 0.4, 0.9)
print(round(p, 5), (13 + np.sqrt(1609))/80) # 0.66390 0.66390