Library · The Fiddler: Solutions · Chapter 139
Can You Ride out the Slow Car Chase?
You are in a car chase in which both cars obey every traffic law and stop at every red light. You are one block ahead of your pursuer, and both of you are waiting at red lights. The lights turn green together, and both cars head east at one block per minute.
At every intersection the light is green with probability , and you coast through, or red with probability , and it turns green after exactly one minute. Your pursuer’s lights behave the same way, independently of yours, even at the same intersections. Counting the light you are stopped at, there are five lights between you and the city limit, so six for your pursuer. How likely are you to cross the city limit without being caught?
The Fiddler, Zach Wissner-Gross, October 20, 2023(original post)
The official solution appeared in the post of October 27, 2023 and gives for the main puzzle and an infinite average for the Extra Credit. Both agree with the answers below.
Solution
Number the blocks so that you start at block and your pursuer at block ; the city limit is just past block . Both cars move at the same speed, so the pursuer can never close the gap on the road. It can only catch you while you are waiting at a red light.
When are you caught? Call your lights at blocks your first, second, third and fourth lights, and the pursuer’s lights at blocks its first to fourth. Let and be the number of reds you and the pursuer meet among your first lights. You leave block at time : minutes of driving and minutes of waiting, the last possibly at block itself. The pursuer reaches block at time . So it catches you there exactly when (When it happens, the pursuer pulls up just as your light turns green: the official solution counts that as caught, and so does this one.) So you escape exactly when the pursuer’s extra waiting, , stays at or more for .
A walk made of coin flips. At each light goes up by (your light green, theirs red), down by (the reverse), or stays put (both the same), with probabilities . Here is the one idea of the solution. Score each light as a fair coin flip of : the pursuer’s light for red and for green, and yours for green and for red. Half the sum of the two scores is exactly the change in (check the four cases). So after pairs of lights, where is the running total of fair coin flips of : a simple random walk, taking steps in all for the four pairs of lights. You escape exactly when are all at least . A walk of steps is even after an even number of steps and odd after an odd number, so this is the same as saying that the walk never reaches in its steps.
Counting with a mirror. Of the walks, those ending at number :
| end | |||||||||
| walks |
An escaping walk ends at or above. Some walks that end at or above do reach along the way. Take such a walk and reflect everything after its first visit to , mirroring it in the level ; it now ends at , which is or below. Every walk ending at or below must pass , and reflecting it back recovers the original, so these bad walks match up one to one with the walks ending at or below. The escapes are the walks ending at or above, less these : that is , exactly the walks ending at or . So
The computation
The check makes no use of the walk. It replays the chase minute by minute for all equally likely patterns of red and green at the lights that matter (your four after the start, the pursuer’s five) and adds up the probability of the patterns in which the pursuer never reaches you while you are still at an intersection.
from fractions import Fraction
from itertools import product
def caught(mine, theirs):
"""Replay the chase minute by minute. I wait at block 1
and the pursuer at block 0; both lights turn green at time
0 and the city limit is just past block 5. mine[k] and
theirs[k] are 1 if the light at block k is red when that
car arrives (a red light costs one minute), else 0."""
leave_me, t = {1: 0}, 0
for k in range(2, 6):
t = t + 1 + mine[k] # one block, then wait
leave_me[k] = t
t = 0
for k in range(1, 6):
t = t + 1 # pursuer arrives at k
if k >= 2 and t <= leave_me[k]:
return True # I am still there
t = t + theirs[k]
return False
escapes = Fraction(0)
for bits in product([0, 1], repeat=9):
mine = dict(zip(range(2, 6), bits[:4]))
theirs = dict(zip(range(1, 6), bits[4:]))
if not caught(mine, theirs):
escapes += Fraction(1, 2 ** 9)
print("main: escape with probability", escapes)
It prints
main: escape with probability 63/128
Extra Credit
Now the city goes on for ever. Starting as before, how many minutes, on average, until you are caught?
Solution
The mirror argument works for any number of lights. You are still free after pairs of lights exactly when the walk of steps has not reached , and the same reflection shows that these walks are the ones ending at or . So This shrinks to zero, so you are caught in the end with certainty. But it shrinks slowly. Write as a product, Each factor with is at least , since . So is at least , and multiplying by this second product makes almost everything cancel: The average number of lights you pass before being caught is the sum of the chances of still being free after lights (each light you get past adds one to ). So and this sum has no limit: its terms shrink too slowly (the first of them add up to more than , since each is at least ). Every light passed takes at least a minute, so Capture is certain, yet its average time is infinite: long escapes are rare, but not rare enough. The median, by contrast, is short. You are still free after three lights with chance and after four with , so half of all chases are over by the fourth light.
The computation
An infinite average cannot be printed, but its signature can. The program tracks the exact distribution of the pursuer’s extra waiting, light by light, as the replay above defines it, dropping the cases in which you have been caught. It reports the chance of still being free after lights and the lower bound for the average number of lights given by the first of them. The chance falls roughly like , and the bound keeps climbing, roughly like , with no sign of levelling off.
# Endless city. As the replay shows, after each pair of lights
# the pursuer's lateness behind me changes by (their red) minus
# (my red); I am caught once it drops below zero. Track its
# distribution exactly, light after light.
lead = {0: 1.0} # lateness -> probability, not caught
survive = []
for n in range(1, 2001):
new = {}
for d, p in lead.items():
for step, q in ((-1, 0.25), (0, 0.5), (1, 0.25)):
if d + step >= 0:
new[d + step] = new.get(d + step, 0) + p * q
lead = new
survive.append(sum(lead.values()))
for n in (10, 100, 1000, 2000):
s, low = survive[n - 1], 1 + sum(survive[:n])
print(f"{n:4} lights: free {s:.4f}, mean >= {low:.1f}")
It prints
10 lights: free 0.3364, mean >= 5.7
100 lights: free 0.1121, mean >= 20.8
1000 lights: free 0.0357, mean >= 69.4
2000 lights: free 0.0252, mean >= 99.0