Skip to content
Vamshi Jandhyala

Books · The Fiddler: Solutions

Chapter 61

Can You Root for the Underdog?

In a four-team bracket each team has a power index of 55 minus its seed (so the 11-seed has power 44, the 44-seed power 11). In every matchup the underdog (lower power) gets a fixed boost BB, a positive non-integer, and the higher adjusted power wins. The bracket is 11 vs 44 and 22 vs 33, winners meet. Of the four teams, how many can never win the bracket, whatever BB is?

The Fiddler, Zach Wissner-Gross, March 28, 2025(original post)

Solution

Sweep BB across all positive values and record the champion. The 11-seed wins for small BB, the 44-seed for large BB, and the 33-seed in a middle band; but the 22-seed is always squeezed out, beaten in one round or the next for every BB. So exactly 1 team (the 2-seed) can never win.\boxed{1}\ \text{team (the $2$-seed) can never win.}

The computation

Encode the bracket and sweep the boost: for a fine grid of BB values, play out the two rounds with the underdog bonus and collect the set of possible champions. The teams never appearing are the ones that can never win.

import numpy as np
power = {1: 4, 2: 3, 3: 2, 4: 1}
def champ(B):
    def play(a, b):
        pa = power[a] + (B if power[a] < power[b] else 0)
        pb = power[b] + (B if power[b] < power[a] else 0)
        return a if pa > pb else b
    return play(play(1, 4), play(2, 3))
print(4 - len({champ(B) for B in np.linspace(1e-4, 50, 500_000)}))   # 1

Extra Credit

Now there are 6464 teams seeded 11 to 6464, power index 6565 minus seed, in a standard bracket. How many can never win?

Solution

The same sweep over BB, run on the full 6464-team bracket, leaves 27 teams that can never win\boxed{27}\ \text{teams that can never win} (so 3737 can). (The source’s count is paywalled; this is my own.)

The computation

The same boost sweep, now folding a standard 6464-team seeding round by round.

def order(k):
    o = [1, 2]
    for r in range(1, k):
        m = 2**(r + 1) + 1; o = [x for pr in zip(o, [m - x for x in o]) for x in pr]
    return o
seeds = order(6); power = {s: 65 - s for s in range(1, 65)}
def champ(B):
    t = seeds[:]
    while len(t) > 1:
        t = [a if power[a] + (B if power[a] < power[b] else 0)
                  > power[b] + (B if power[b] < power[a] else 0)
             else b for a, b in zip(t[::2], t[1::2])]
    return t[0]
print(64 - len({champ(B) for B in np.linspace(1e-4, 80, 200_000)}))   # 27