Edit:
Thanks a lot for your help @Peilonrayz and @Marc! I have modified my code according to your suggestions, and now it looks something like this:
import random
import statistics
def simulation(days_in_year):
days = [0] * days_in_year
num_emperors = 0
holidays = 0
#increments (as suggested) is slightly faster than while not all(days)
while holidays < days_in_year:
#also, slightly faster than np.random.randint. But why?
bday = random.randint(0, days_in_year - 1)
num_emperors += 1
if days[bday] == 0:
days[bday] = 1
holidays += 1
else:
continue
yesterday = (bday - 1) % days_in_year
day_before_yesterday = (bday - 2) % days_in_year
if days[day_before_yesterday] == 1 and days[yesterday] == 0:
days[yesterday] = 1
holidays += 1
tomorrow = (bday + 1) % days_in_year
day_after_tomorrow = (bday + 2) % days_in_year
if days[day_after_tomorrow] == 1 and days[tomorrow] == 0:
days[tomorrow] = 1
holidays += 1
return num_emperors
def monte_carlo(iters, days):
for _ in range(iters):
yield simulation(days)
The time required has become as followed:
avg_n_emperor = statistics.mean(monte_carlo(iters = 1000, days = 360)) #about 1.7 seconds
avg_n_emperor = statistics.mean(monte_carlo(iters = 100000, days = 360)) #about 170 seconds
avg_n_emperor = statistics.mean(monte_carlo(iters = 100000, days = 730)) #about 400 seconds
The correlation between time and iters & days is already becoming linear. I will try to modify a bit more and see where it goes :)