Hey guys. I decided to do another project euler problem, and got this problem:

You are given the following information, but you may prefer to do some research for yourself.

    * 1 Jan 1900 was a Monday.
    * Thirty days has September,
      April, June and November.
      All the rest have thirty-one,
      Saving February alone,
      Which has twenty-eight, rain or shine.
      And on leap years, twenty-nine.
    * A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.

How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?

After I come up with an algorithm, I normally check it against other one's on the web. Mine oddly seems faster and simpler than all the one's I've seen (never happend befor). I just want to make sure it makes sence, and I'm not missing something. Here is the algorithm:

year = 1901
day = 1      //tuesday
sum = 0

while year is less than 2001
  day += 31
  sum += day/7  //add the number of sundays in this january to sum
  day %= 7      //this is the day that this january end on
  
  if year is divisable by 4 and year is not divisible by 100  //leap year
    day += 335
  else if year is divisable by 4 and divisable by 100         //leap year
    day += 335
  else                                                        //not leap year
    day += 334
  
  day %= 7    //day now equals the first day fo january
  year++

Is there something I'm missing?
The other algorithms I've seen seem to use the fact that there are 1200 months in a century and requre a counter for day, week, month, year and sum.
Thanks.

Dani AI

Generated

Nice start, — and good catch by on the leap-year edge case. Two separate issues to watch for here: your loop as written counts how many Sundays occur inside January, not how many months begin on a Sunday; and the leap-year test must include the "divisible by 400" exception (so 1900 is not a leap year, 2000 is).

A minimal, robust approach (no heavy state machine) is this in plain words: keep a single variable that holds the weekday of the first day of the current month. Initialize it to the weekday for 1 Jan 1901 (Tuesday). For each month from Jan 1901 through Dec 2000, test whether that weekday equals Sunday and increment a counter if so. Then advance the weekday by (days_in_that_month modulo 7) and reduce modulo 7 to get the first-day weekday for the next month. Use the usual month lengths and the correct leap rule: year % 4 == 0 and (year % 100 != 0 or year % 400 == 0).

Troubleshooting tips: pick a clear mapping for weekdays (for example Sunday=0) and stick to it; never use integer division like day/7 to decide whether the first of the month is a Sunday (that counts occurrences, not starts); and double-check that your start date is 1 Jan 1901 (the problem excludes 1900). A quick sanity test is to run the routine for a small known window and compare to a calendar.

The canonical answer for Project Euler Problem 19 is 171 months whose first day is Sunday between 1 Jan 1901 and 31 Dec 2000. The month-iteration method above is simple, fast (1200 iterations) and easy to unit-test, so it avoids the off-by-one and logic pitfalls you ran into.

Recommended Answers

All 3 Replies

This: if year is divisable by 4 and year is not divisible by 100 //leap year is not complete. A leap year is a year that's divisable by 4 and not by 100 unless it can be divided by 400.

Other then that, it looks fine.

Your right. I've finally got to implement it (14 hour drive) and it has problems still. I'll check over it again when I'm back home. I'm going to mark it as solved, since atleast one person thinks my algorithm is almost fine.
Thanks :)

Hehe... Yup I missed something. The question asked how many Sundays fall on the first of each month. Not how many Sundays fall on the first month. I knew there was something up :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.