Monte Carlo Simulations for Ultramarathon Lotteries

Lottery balls - image by dylan_nolte on Unsplash

I've entered the lotteries for both Hardrock 100 and Western States 100 for several years, without any luck so far. Both races hold lotteries in December to draw the "lucky" winners that get to run their races. Both end up posting the odds that everyone has based on how many tickets you have in the lottery. They do this by running a Monte Carlo simulation several thousand (or millions) of times. Out of curiosity, this year I decided to write a program to do the simulation myself. Now I can find out my odds before the races officially post them! But I didn't really do it for that but just as an exercise to do as programmers are wont to do.

You can find the code for Hardrock and Western States on GitHub. Instructions for running the code are on the README on the repos.

There is nothing terribly complex about either implementation though Hardrock has much more complicated rules so the logic is more complex. Running 1,000 simulations takes about 6 minutes for Hardrock and 7 minutes for Western States, so it's not terribly efficient if you are wanting to run something like 1 million simulations (the code sets the max to 10,000 if running through `main.rb`). However, I think 10,000 simulations seems to approximate the odds very closely to what the races post even though they do many more simulations.

The code includes the race entrants hard-coded because it seemed pointless to try and accept the entrants as a complex input parameter. I originally committed the code with 2023 lottery data, but then updated them for the 2024 lottery.

Here are the results of my own simulation runs. It's important to note that neither is considering the probability of making the waitlist. For Western States, including the waitlist increases your probability by about 0.1% for the low ticket counts and about 7% for the 256 ticket entrants. Hardrock selects so many people to the waitlist that getting on the waitlist doesn't necessarily mean that you have any chance at all of getting to the start line.

Western States probability:

{
  1=>0.54,
  2=>1.08,
  4=>2.14,
  8=>4.24,
  16=>8.36,
  32=>15.94,
  64=>29.43,
  128=>50.12,
  256=>74.54
}

Hardrock probability:

{
  "men finished 2"=>13.7,
  "men finished 3"=>19.68,
  "men finished 4"=>25.0,
  "men finished 5"=>30.82,
  "men finished 6"=>35.55,
  "men finished 7"=>39.79,
  "men finished 8"=>45.04,
  "men finished 9"=>46.65,
  "men finished 10"=>52.03,
  "men finished 11"=>55.03,
  "men finished 12"=>55.8,
  "men finished 13"=>61.4,
  "men finished 15"=>66.37,
  "men finished 19"=>72.4,
  "men never 1"=>0.27,
  "men never 2"=>0.55,
  "men never 4"=>1.07,
  "men never 8"=>2.22,
  "men never 16"=>4.19,
  "men never 32"=>8.39,
  "men never 64"=>16.14,
  "men never 128"=>29.93,
  "men never 256"=>51.48,
  "men never 512"=>76.29,
  "men never 2048"=>99.1,
  "women finished 2"=>16.98,
  "women finished 3"=>24.88,
  "women finished 4"=>31.18,
  "women finished 5"=>37.24,
  "women finished 6"=>42.9,
  "women finished 7"=>48.0,
  "women finished 8"=>53.0,
  "women finished 20"=>85.4,
  "women never 1"=>0.34,
  "women never 2"=>0.69,
  "women never 4"=>1.35,
  "women never 8"=>2.71,
  "women never 16"=>5.39,
  "women never 32"=>10.73,
  "women never 64"=>20.24,
  "women never 128"=>35.76,
  "women never 256"=>60.02
}