Asher E
Asher E

Reputation: 33

Project Euler #19 - Counting Sundays Problem

I have been working on this problem for a while. It's a problem that says you have to find how many Sundays land on the First of the Month in the years 1901 to 2000. I've made it mostly work, but it still outputs 173, instead of 171 (the correct answer).

Does anyone why this is?

months = {1:31, 2:28, 3:31, 4:30, 5:31, 6:30, 7:31, 8:31, 9:30, 10:31, 11:30, 12:31}

start, end = 1900, 2001

years = range(start, end)
leap_years = range(1904, 2001, 4)

Sundays = 0
days = 1
for year in years:
  if year in leap_years:
    months[2] = 29 
  else:
    months[2] = 28

  for month in range(1, 13):
    for day in range(1, months[month]+1):
      if days == 7:
        if day == 1:
          print(year, month, day)
          Sundays += 1
        days = 1
      else:
        days += 1


print(Sundays)

Upvotes: 3

Views: 1301

Answers (4)

OffHakhol
OffHakhol

Reputation: 101

My solution in python below. You can make it shorter at least by dividing the numbers of lines by 2 but this way (at least for me) we clearly see how the algorithm works.

day_by_month = [31,28,31,30,31,30,31,31,30,31,30,31]
day_by_month_leap_year = [31,29,31,30,31,30,31,31,30,31,30,31]

# Date format day of the week/day/month/year
init = [0, 1, 1, 1900]  # monday 1 January 1900 - Monday 01/01/1900
ite = init
ans = 0
i=0

while ite[3] < 2001:
    if (ite[3] % 4 == 0 and ite [3] % 100 != 0) or (ite[3] % 400 == 0):
        ite[0] = (ite[0] + day_by_month_leap_year [i])%7 # update day of the week
        ite[2] = (ite[2] +1)%12 # update the month
        if ite[0] == 6 and ite[3] != 1900:
            ans = ans + 1
            print(ite)
        i=i+1
    else:
        ite[0] = (ite[0] + day_by_month[i]) % 7  # update day of the week
        ite[2] = (ite[2] + 1)%12  # update the month
        if ite[0] == 6 and ite[3] != 1900:
            ans = ans + 1
            print(ite)
        i = i + 1
    if i % 12 == 0 :
        i = 0
        ite[3] = ite[3] + 1 # update year

print(ans)

Upvotes: 0

mohammad eska
mohammad eska

Reputation: 1

import datetime

def sunday_finder(start_year , stop_year):
    recent_year = start_year
    counter = 0
    for course_of_y in range ((stop_year-start_year)+1): #to find The gap between years
        for month in range(1,13):                          #to ireration all months
            date = datetime.datetime(recent_year , month, 1)   #first day of every mounth
            if int(date.strftime("%w")) == 0:                
                counter += 1
        recent_year += 1         #to start next year in next itenration
    return counter

Upvotes: 0

Chris Charley
Chris Charley

Reputation: 6613

Your days assumes day equal 1 is days equal 1, (Monday) starting from the first month (and then progresses through the months, years). I don't think this will accurately calculate the count of Sundays that fall on the first of each month over the years.

If you enter the following code at the beginning of your program (and delete the line before your loop that says days = 1), it will correctly give the number of Sundays == 171. This will start out the day of week for the first day of the first month of the first year accurately.

from calendar import weekday
start, end = 1901, 2001
days = 1 + weekday(start, 1, 1)

Note that the weekday function uses zero based counting, (Monday through Sunday is 0 to 6) so that's why 1 is added to the result in the initialization of days. (Because your Monday to Sunday is 1 to 7).

Just to illustrate how the solution could find Sundays without iterating through every day of all the years:

from calendar import weekday

sundays = 0

for yr in range(1901, 2001):
    for month in range(1, 13):
        if weekday(yr, month, 1) == 6:
            sundays += 1

print(sundays) # prints 171

Upvotes: 0

Gbox4
Gbox4

Reputation: 633

Your algorithm is completely correct - just the inputs are wrong. start and end should be:

start, end = 1901, 2000

The range(a, b) function is not inclusive of b, but it is inclusive of a. Thus start should be 1901 instead of 1900.

The end is a bit more tricky, you have to think about the phrasing of the question:

... in the years 1901 to 2000

Think about it - this means every day up to, but not including, Jan 1 2000. Thus the last year that you actually want to iterate through and check is 1999. Thus, setting end to 2000 will cause the range() function to return all the years up to, but not including, 2000. Which is exactly what the question asks for.

Upvotes: 2

Related Questions