Chapter 241
What Are Your Chances Of Winning The U.S. Open?
Riddler Express
In “Acchi, Muite, Hoi” (the lookaway challenge), you and a friend alternate roles. The pointer points in one of four directions (up, down, left, right) while the looker simultaneously looks in one of the four. If the looker looks where the pointer points, the pointer wins; otherwise they swap roles and play again. You point first, and both of you choose randomly each round. What is your probability of winning?
The Riddler, FiveThirtyEight, September 6, 2019(original post)
Solution
It is not : pointing first is a real edge, because only the pointer can win a round. Let be the probability that whoever is currently pointing eventually wins the game. On this round the pointer wins outright with probability (the directions match). With probability no one wins, the roles swap, and the other player is now the pointer, who then wins with probability , so the current player wins with probability . Hence You are the first pointer, so your chance of winning is The same answer falls out of summing the odd rounds (you can only win when you point, in rounds ): .
The computation
Encode the actual game: alternate pointer and looker, each picking one of four directions at random, until a round’s directions match, and record whether the first pointer (you) won. The frequency should sit at .
import random
rng = random.Random(0); wins = 0; T = 2_000_000
for _ in range(T):
pointer = 0 # 0 = you, the first pointer
while True:
if rng.randrange(4) == rng.randrange(4):
wins += (pointer == 0); break
pointer ^= 1 # no match: swap roles
print(f"simulated {wins / T:.4f} vs 4/7 = {4/7:.4f}")
# simulated 0.5718 vs 4/7 = 0.5714
Riddler Classic
At the U.S. Open you win each point with probability . Tennis scoring: a game goes to points, win by ; a set goes to games, win by , with a tiebreaker to points (win by ) at -; a match is best of three sets (women) or best of five (men). What are your chances of winning a three-set match, a five-set match, and the whole tournament (seven straight matches)?
The Riddler, FiveThirtyEight, September 6, 2019(original post)
Solution
Tennis scoring is steeply nonlinear: a small per-point edge compounds through the nested “win by two” races. Work from the inside out. A game and a tiebreaker are both races to a target won by two; from a tied-near-the-top score (deuce), the chance of winning is with , and unwinding the rest of the game gives the chance of holding from -. Feeding the game probability into the same kind of race over games (with a tiebreaker at -) gives the set probability, and from there the match and tournament follow.
Carried out with , the chance of winning a set is about , and then
Playing more sets helps the stronger player, which is why the five-set tournament probability is so much higher. The lesson is that of points is not “slightly better”: it is roughly the career rate of the all-time greats.
The computation
Encode each “race to , win by ” as a recursion on the current score, with the deuce region handled by its closed form, and compose: game and tiebreaker as point races, the set as a race over games (tiebreaker at -), the match as best-of, the tournament as seven matches.
from functools import lru_cache
from math import comb
p = 0.55
def deuce(q): return q * q / (q * q + (1 - q) ** 2)
def race(q, N): # P(win race to N, win by 2) from 0-0
@lru_cache(None)
def f(a, b):
if a >= N - 1 and b >= N - 1:
d = a - b; D = deuce(q)
return 1.0 if d >= 2 else 0.0 if d <= -2 else \
D if d == 0 else q + (1 - q) * D if d == 1 else q * D
if a >= N and a - b >= 2: return 1.0
if b >= N and b - a >= 2: return 0.0
return q * f(a + 1, b) + (1 - q) * f(a, b + 1)
return f(0, 0)
game, tb = race(p, 4), race(p, 7)
@lru_cache(None)
def setp(a, b):
if a == 6 and b == 6: return tb # tiebreaker
if a >= 6 and a - b >= 2 or a == 7: return 1.0
if b >= 6 and b - a >= 2 or b == 7: return 0.0
return game * setp(a + 1, b) + (1 - game) * setp(a, b + 1)
s = setp(0, 0)
def match(n): # best of (2n-1) sets
return sum(comb(n - 1 + k, k) * s ** n * (1 - s) ** k for k in range(n))
m3, m5 = match(2), match(3)
print(f"set={s:.3f} 3-set={m3:.3f} 5-set={m5:.3f}")
print(f"tournament women={m3**7:.3f} men={m5**7:.3f}")
# set=0.815 3-set=0.910 5-set=0.953
# tournament women=0.517 men=0.714
The recursion reproduces the set, the and matches, and the and tournament chances.