Books · The Fiddler: Solutions
Chapter 93
Can You Ace the Technical Interview?
Start with a segment of length . Split it at a uniformly random point into two pieces and record the product of the two lengths. Then split each piece the same way, recording each product, and continue forever, splitting every piece that appears. On average, what does the running sum of all these products approach?
The Fiddler, Zach Wissner-Gross, May 31, 2024(original post)
Solution
Let be the expected sum of all products generated from a segment of length . Splitting at a uniform point contributes one product and then leaves two independent sub-problems, so Everything scales as area, so write . The first term is , and each of the other two is . Hence At the expected total is
The computation
Run the actual process: keep splitting every piece at a uniform point, accumulating products, until the pieces are negligibly small, and average over many realisations. It lands on .
import numpy as np
def total(eps=1e-3): # one realisation, split until pieces < eps
stack, s = [1.0], 0.0
while stack:
L = stack.pop()
if L < eps: continue
x = np.random.random() * L
s += x * (L - x); stack += [x, L - x]
return s
np.random.seed(1)
print(np.mean([total() for _ in range(8000)])) # ~0.500
Extra Credit
Now split into three pieces (uniform on ) and score by the recursion On average, what does approach?
Solution
Now scales as a volume, so write . A uniform split of into three is a Dirichlet distribution scaled by , whose moments are , , and . Taking expectations of the recursion and using the symmetry of , So
The computation
A direct simulation of branches six ways and explodes, so instead measure the three moments the recursion actually depends on by sampling the uniform three-way split, then solve the self-consistency . The sampled moments give .
import numpy as np
rng = np.random.default_rng(0); N = 5_000_000
a, b, c = rng.dirichlet([1, 1, 1], N).T # uniform split of 1 into three
E_abc = (a * b * c).mean() # ~ 1/60
E_pair = ((a + b) ** 3).mean() # ~ 2/5
E_single = (a ** 3).mean() # ~ 1/10
print(round(E_abc / (1 - 3*E_pair + 3*E_single), 4)) # ~0.1667 = 1/6