2
\$\begingroup\$

I'm working on Project Euler problem 19, which reads as follows:

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)?

Note that my title is slightly misleading because this isn't counting all of the Sundays in the 20th Century, just the ones that fall on the first day of the month.

Here's my code:

public int HowManySundays()
    {
        // Have an array with the number of days in each month. For example, month 0 is January,
        // which has 31 days.
        int[] daysInEachMonth = new int[]
        {
            31,
            28,
            31,
            30,
            31,
            30,
            31,
            31,
            30,
            31,
            30,
            31
        };

        int currentYear = 1900;

        // First year in 1900
        // We could calculate the first Sunday in 1901 to save a little time
        // but that's not all *that* much of an optimization so it's not terribly important
        int currentDay = 7;

        int currentMonth = 0;

        int numberOfSundays = 0;

        while (currentYear < 2001)
        {
            // Add 7 each time so that we know that it's another Sunday
            currentDay += 7;

            // I don't particularly like the special reasoning for February for leap-year detection
            // We don't actually have to do separate logic for centuries because the only century we
            // care about is the year 2000, which we already know is evenly divisible by 400
            int daysInMonth =
                currentMonth == 1 ?
                    ((currentYear % 4 == 0) ? 29 : 28) :
                    daysInEachMonth[currentMonth];

            if (daysInEachMonth[currentMonth] < currentDay)
            {
                currentDay -= daysInEachMonth[currentMonth];
                currentMonth++;

                // Months are 0 - 11
                // See if we've wrapped around to a new year
                if (currentMonth >= 12)
                {
                    currentMonth = 0;
                    currentYear++;
                }

                // If day == 1, then it must be a Sunday on the first day of the month
                if (currentDay == 1 && currentYear > 1900)
                {
                    numberOfSundays++;
                }
            }
        }

        return numberOfSundays;
    }

I have a trivial unit test (not included here) proving that my method does, in fact, return the correct answer (171).

Does anyone have feedback on this (especially on its readability)? Is this decently efficient, or did I miss some optimizations?

\$\endgroup\$
4
\$\begingroup\$

Your logic is checking about Number of Days in Month, Leap year and related date logic.

Following snippet will work. This logic will loop thru the each month(1 to 12) with in 20th century and and checks first day of month is Sunday or not.

      var result = 0;
        for(int year =  1901; year <= 2000; year++)
        {
            for(int month = 1;month<=12;month++)
            {
                if (new DateTime(year, month, 1).DayOfWeek == DayOfWeek.Sunday)
                    result++;
            }
        }
        Console.WriteLine(result);
\$\endgroup\$
  • \$\begingroup\$ True, that's possible as well. \$\endgroup\$ – EJoshuaS Aug 14 '17 at 20:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.