Western States 100 Lottery
Introduction
The Western States 100 mile endurance event is held every June in California since 1974. In a field of 369 runners, 260 can earn a spot on the starting line through a lottery process. Each year, entrants must complete a 100k or 100mi qualifying race. The number of tickets you have in the lottery is 2n-1, where n is the number of years you have entered to lottery (n resets once you are selected).
More details are described on the race website.
This year I have 8 tickets because it is my 4th year entering the lottery.
| Year | Race | Distance | Time |
|---|---|---|---|
| 2022 | Massanutten Mountain Trails (VA) | 100mi | 26:32:42 |
| 2023 | Twisted Branch (NY) | 100k | 19:09:25 |
| 2024 | Twisted Branch (NY) | 100k | 18:24:59 |
| 2025 | Massanutten Mountain Trails (VA) | 100mi | 22:38:46 |
Lottery Entrants
Code
# number of people with the respective number of tickets
one <- 4471
two <- 2563
four <- 1754
eight <- 1102
sixteen <- 672
thirtytwo <- 354
sixtyfour <- 240
onetwentyeight <- 129
twofiftysix <- 45
fivetwelve <- 5
# assign each person a unique ID
tix001 <- (1:one)
tix002 <- (1:two) + max(tix001)
tix004 <- (1:four) + max(tix002)
tix008 <- (1:eight) + max(tix004)
tix016 <- (1:sixteen) + max(tix008)
tix032 <- (1:thirtytwo) + max(tix016)
tix064 <- (1:sixtyfour) + max(tix032)
tix128 <- (1:onetwentyeight) + max(tix064)
tix256 <- (1:twofiftysix) + max(tix128)
tix512 <- (1:fivetwelve) + max(tix256)
# create the complete lottery pool
tickets <- c(rep(tix001,1),
rep(tix002,2),
rep(tix004,4),
rep(tix008,8),
rep(tix016,16),
rep(tix032,32),
rep(tix064,64),
rep(tix128,128),
rep(tix256,256),
rep(tix512,512))Number of entrants: 11335
Number of tickets: 93461
Simulation Results
I performed 1,000,000 simulations to approximate the probability of being selected for each ticket count. An exact probability cannot be calculated because once a ticket is selected, every other ticket from that individual is removed from the pool.
Code
# counters for the number of simulations in which
# a person with that number of tickets is selected
counter001 <- 0
counter002 <- 0
counter004 <- 0
counter008 <- 0
counter016 <- 0
counter032 <- 0
counter064 <- 0
counter128 <- 0
counter256 <- 0
counter512 <- 0
# number of simulations
n_sim <- 1000000
# simulation for-loop
for (i in 1:n_sim) {
winners <- c()
while (length(winners)<260) {
selection <- sample(tickets, size = 1, replace = F)
winners <- unique(c(winners,selection))
}
if (tix001[1] %in% winners) { counter001 <- counter001 + 1 }
if (tix002[1] %in% winners) { counter002 <- counter002 + 1 }
if (tix004[1] %in% winners) { counter004 <- counter004 + 1 }
if (tix008[1] %in% winners) { counter008 <- counter008 + 1 }
if (tix016[1] %in% winners) { counter016 <- counter016 + 1 }
if (tix032[1] %in% winners) { counter032 <- counter032 + 1 }
if (tix064[1] %in% winners) { counter064 <- counter064 + 1 }
if (tix128[1] %in% winners) { counter128 <- counter128 + 1 }
if (tix256[1] %in% winners) { counter256 <- counter256 + 1 }
if (tix512[1] %in% winners) { counter512 <- counter512 + 1 }
}
# calculate percentages for each ticket count
percent001 <- counter001*100/n_sim
percent002 <- counter002*100/n_sim
percent004 <- counter004*100/n_sim
percent008 <- counter008*100/n_sim
percent016 <- counter016*100/n_sim
percent032 <- counter032*100/n_sim
percent064 <- counter064*100/n_sim
percent128 <- counter128*100/n_sim
percent256 <- counter256*100/n_sim
percent512 <- counter512*100/n_sim
# output table of results
kable(
data.frame(
`Number of tickets` = c(
"1 ticket", "2 tickets", "4 tickets", "8 tickets", "16 tickets",
"32 tickets", "64 tickets", "128 tickets", "256 tickets", "512 tickets"
),
`Probability` = c(
paste0(format(round(percent001,2),nsmall=2),"%"),
paste0(format(round(percent002,2),nsmall=2),"%"),
paste0(format(round(percent004,2),nsmall=2),"%"),
paste0(format(round(percent008,2),nsmall=2),"%"),
paste0(format(round(percent016,2),nsmall=2),"%"),
paste0(format(round(percent032,2),nsmall=2),"%"),
paste0(format(round(percent064,2),nsmall=2),"%"),
paste0(format(round(percent128,2),nsmall=2),"%"),
paste0(format(round(percent256,2),nsmall=2),"%"),
paste0(format(round(percent512,2),nsmall=2),"%")
),
`Number of applicants` = c(
one,two,four,eight,sixteen,thirtytwo,sixtyfour,
onetwentyeight,twofiftysix,fivetwelve
),
`Number selected` = c(
format(round(one*percent001/100,1),nsmall=1),
format(round(two*percent002/100,1),nsmall=1),
format(round(four*percent004/100,1),nsmall=1),
format(round(eight*percent008/100,1),nsmall=1),
format(round(sixteen*percent016/100,1),nsmall=1),
format(round(thirtytwo*percent032/100,1),nsmall=1),
format(round(sixtyfour*percent064/100,1),nsmall=1),
format(round(onetwentyeight*percent128/100,1),nsmall=1),
format(round(twofiftysix*percent256/100,1),nsmall=1),
format(round(fivetwelve*percent512/100,1),nsmall=1)
)
)
)| Number.of.tickets | Probability | Number.of.applicants | Number.selected |
|---|---|---|---|
| 1 ticket | 0.31% | 4471 | 14.0 |
| 2 tickets | 0.62% | 2563 | 16.0 |
| 4 tickets | 1.25% | 1754 | 21.9 |
| 8 tickets | 2.48% | 1102 | 27.3 |
| 16 tickets | 4.82% | 672 | 32.4 |
| 32 tickets | 9.50% | 354 | 33.6 |
| 64 tickets | 18.11% | 240 | 43.5 |
| 128 tickets | 32.97% | 129 | 42.5 |
| 256 tickets | 55.00% | 45 | 24.8 |
| 512 tickets | 79.77% | 5 | 4.0 |