En Garde! Can You Win The Fencing Relay?

A FiveThirtyEight Riddler puzzle.

By Vamshi Jandhyala in mathematics Riddler

December 10, 2021

Riddler Express

My condo complex has a single elevator that serves four stories: the garage $(G)$, the first floor $(1)$, the second floor $(2)$ and the third floor $(3)$. Unfortunately, the elevator is malfunctioning and stopping at every single floor, no matter what. The elevator always goes $G, 1, 2, 3, 2, 1, G, 1, 2,$ etc.

I want to board the elevator on a random floor (with all four floors being equally likely). As I round the corner to approach the elevator, I hear that its doors have closed, but I have no further information about which floor it’s on or whether the elevator is going up or down. The doors might have just closed on my floor, for all I know.

On average, how many stops will the elevator make until it opens on my floor (including the stop on your floor)? For example, if I am waiting on the second floor, and I heard the doors closing on the garage level, then the elevator would open on my floor in two stops.

Extra credit: Instead of four floors, suppose my condo had $N$ floors. On average, how many stops will the elevator make until it opens on my floor?

Computational Solution

From the simulation below, we see that the average number of stops when there are $\textbf{four}$ floors is $\textbf{2.83}$.

from itertools import cycle
from random import choice, randint

def avg_stops(n = 4, runs = 100000):
    rotate = lambda l, n: l[-n:] + l[:-n]
    floors, elevator_cycle = list(range(n)), list(range(n)) + list(range(n-2,0,-1))
    total_stops = 0
    for _ in range(runs):
        my_floor, start = choice(floors), randint(0, len(elevator_cycle)-1)
        for f in cycle(rotate(elevator_cycle, start)):
            total_stops += 1
            if f == my_floor:
                break
    return total_stops/runs

print(avg_stops())

Riddler Classic

You are the coach at Riddler Fencing Academy, where your three students are squaring off against a neighboring squad. Each of your students has a different probability of winning any given point in a match. The strongest fencer has a $75$ percent chance of winning each point. The weakest has only a $25$ percent chance of winning each point. The remaining fencer has a $50$ percent probability of winning each point.

The match will be a relay. First, one of your students will face off against an opponent. As soon as one of them reaches a score of $15$, they are both swapped out. Then, a different student of yours faces a different opponent, continuing from wherever the score left off. When one team reaches $30$ (not necessarily from the same team that first reached $15$), both fencers are swapped out. The remaining two fencers continue the relay until one team reaches $45$ points.

As the coach, you can choose the order in which your three students occupy the three positions in the relay: going first, second or third. How will you order them? And then what will be your team’s chances of winning the relay?

Computational Solution

From the simulation below, we see that the probability of the permutation $\textbf{weakest, medium, strongest}$ winning is the highest at $\approx\textbf{93%}$.

from itertools import permutations
from random import random

def winning_probabilities(runs = 100000):
    win_prob = {'w':0.25,'s':0.75, 'm':0.5}
    probs = []
    for p1,p2,p3 in permutations(win_prob.keys()):
        total_wins = 0
        for _ in range(runs):
            s1, s2 = 0, 0
            while (s1 < 15 and s2 < 15):
                if (random() < win_prob[p1]):
                    s1 += 1
                else:
                    s2 += 1
            while (s1 < 30 and s2 < 30):
                if (random() < win_prob[p2]):
                    s1 += 1
                else:
                    s2 += 1
            while (s1 < 45 and s2 < 45):
                if (random() < win_prob[p3]):
                    s1 += 1
                else:
                    s2 += 1
            if s1 == 45:
                total_wins += 1
        probs.append((p1,p2,p3,total_wins/runs))
    return probs

for p1,p2,p3,prob in winning_probabilities():
    print(f"Probability of the permutation {(p1,p2,p3)} winning is {prob}")