Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Solves the fivethirtyeight Riddler Classic from March 29, 2019
# -*- coding: utf-8 -*-
"""
Solves the fivethirtyeight Riddler Classic problem from March 29, 2019
Each speller is identified by their probability of spelling a word correctly,
such as "0.99" to represent a 99% correct speller. The program simulates a
large number of spelling bees and returns the winner of each bee.
"""
import numpy as np
def single_round(spellers):
"""
Play a single round of the spelling bee; draw a random number for each speller,
then compare the number vs. their rate. Each speller that answers correctly
is retained in the array, while incorrect spellers are removed. Returns a new
array of the spellers that advance to the next round.
NOTE : if the function would return an empty array, (in the case that every speller
failed to spell the word correctly) it instead returns the speller listed last in
the original array, who would have won without having to spell a word.
"""
r = np.random.rand(len(spellers))
out = spellers[r < spellers]
if len(out) > 0:
return out
else:
return spellers[-1:]
def bee(spellers):
"""
Run a spelling bee with as many rounds as it takes to eliminate all but one
speller.
"""
while len(spellers) > 1:
spellers = single_round(spellers)
return spellers[0]
def model(spellers, trials):
"""
Run any number of spelling bees and return the winner for each one.
Results returned as a numpy array.
"""
return np.array([bee(spellers) for _ in range(trials)])
def summary(spellers, trials):
"""
Return a dictionary with key=speller, value=wins from the simulated results
NOTE : the order of "p" matters, because the last speller has an advantage
each round. However, the results are shown after sorting the array from
lowest to highest so that different orders of "p" can be compared easily.
"""
results = model(spellers, trials)
return {x: sum(results == x) / trials for x in np.sort(spellers)}
if __name__ == '__main__':
# spellers arranged from best to worst
spellers = np.arange(99, 89, -1) / 100
print(summary(spellers, trials=100000))
# spellers arranged from worst to best
spellers = np.arange(90, 100) / 100
print(summary(spellers, trials=100000))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.