Reputation: 106
I am trying to solve Project Euler Problem 19.
I am not here to ask for the answer to the problem, but I noticed that every time my program runs, its output is different.
Please can someone explain why for me
"""
Author: Luke Spademan
Calculates answer to project euler problem id19
https://projecteuler.net/problem=19
"""
def calculate():
ans = 0
months = {
"jan": 31,
"feb": 28,
"mar": 31,
"apr": 30,
"may": 31,
"jun": 30,
"jul": 31,
"aug": 31,
"sep": 30,
"oct": 31,
"nov": 30,
"dec": 31,
}
i = 1
for year in range(1901, 2001):
for month in months:
months["feb"] = 28
if year % 4 == 0 and not (year % 100 == 0 and year % 400 != 0):
months["feb"] = 29
if i % 7 == 0:
ans += 1
i += months[month]
return ans
if __name__ == "__main__":
answer = calculate()
print(answer)
Upvotes: 6
Views: 1238
Reputation: 54303
Before you get lost in implementation details about dict
s and OrderedDict
s, you could use datetime
to know what the answer should be:
>>> from datetime import date
>>> sum(1 for month in range(1,13) for year in range(1901, 2001) if date(year, month, 1).weekday() == 6)
171
Note that even with Python 3.6 or Python2 + OrderedDict, your code returns 172.
Your sunday test is written as i % 7 == 0
. It means that the 1st day in your loop (1st of january 1901), which is a tuesday, should be initialized with i = 2
.
To avoid any problem with unsorted dicts, you could simply use a list of tuples :
def calculate():
ans = 0
months = [('jan', 31), ('feb', 28), ('mar', 31), ('apr', 30), ('may', 31), ('jun', 30), ('jul', 31), ('aug', 31), ('sep', 30), ('oct', 31), ('nov', 30), ('dec', 31)]
i = 2
for year in range(1901, 2001):
for month_name, days in months:
if month_name == "feb":
if year % 4 == 0 and not (year % 100 == 0 and year % 400 != 0):
days = 29
else:
days = 28
if i % 7 == 0:
ans += 1
i += days
return ans
if __name__ == "__main__":
answer = calculate()
print(answer)
This code returns 171
with any Python version.
Upvotes: 0
Reputation: 59731
The problem is that the result of the computation depends on the order in which months
is iterated. As of Python 3.3, string hashing is randomized by default, meaning that this order will not be deterministic (until Python 3.6). You can read about how to make this program run deterministically here, although I think that your intention is to iterate months
in a predefined order always, in which case it should probably be a list
or an OrderedDict
.
Upvotes: 6