mitcc
mitcc

Reputation: 343

Is there formula to calculate what day is for anyday? I got stuck by Project Euler # 19

I am doing Project Euler #19. Here is states:

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

I have searched in the Internet for some formula to calculate the day of the week. I found the Zeller formula is outstanding. W = [C/4] - 2C + y + [y/4] + [13 * (M+1) / 5] + d - 1.(C is century + 1, and y is last two number of the year) However, it turns to be wrong when I check 1900.01.01, it's should be Monday, but according to the formula, which is 6(that is Saturday)

I have checked a lot of dates, almost all is right for this formula. But there still fewer days doesn't match. My Java code is below for this case:

package number;

public class CountingSundays {

public static int calculateWeek(int year, int month, int date) {
    int c = year / 100;
    int y = year % 100;
    int w = c / 4 - 2 * c + y + y / 4 + 13 * (month + 1) / 5 + date - 1;
    w = (w % 7 + 7) % 7;
    return w;
}

public static void main(String[] args) {
    //      int w = calculateWeek(1900, 01, 01);
    //      System.out.println(w);
    int count = 0;
    for (int i = 1901; i <= 2000; i++) {
        for (int j = 1; j <= 12; j++) {
            if (calculateWeek(i, j, 01) == 0) {
                count++;
            }
        }
    }
    System.out.println(count);
}

} For the mismatch, my output is 173, which is not the required result 171. Anyone can give me some tips? Or is there any wrong with my code?

Upvotes: 1

Views: 600

Answers (3)

Evgeniy Dorofeev
Evgeniy Dorofeev

Reputation: 136092

If you mean Gregorian calendar and English language then

GregorianCalendar gc = new GregorianCalendar(1, Calendar.JANUARY, 1900);
System.out.println(gc.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, Locale.ENGLISH));

output

Monday

etc

Upvotes: 2

Bill the Lizard
Bill the Lizard

Reputation: 405985

You can loop through each month in the specified range of years and set the date on a Calendar object, then read the day of the week for the first of each month.

import java.util.Calendar;
import java.util.GregorianCalendar;

public class CountingSundays {

    public static void main(String[] args) {
        GregorianCalendar gc = new GregorianCalendar(1, Calendar.JANUARY, 1900);

        int count = 0;
        for (int i = 1901; i < 2001; i++) {
            gc.set(GregorianCalendar.YEAR, i);
            for (int j = 0; j < 12; j++) {
                gc.set(GregorianCalendar.MONTH, j);
                if (gc.get(GregorianCalendar.DAY_OF_WEEK) == GregorianCalendar.SUNDAY) {
                    count++;
                }
            }
        }
        System.out.println(count);
    }
}

Note that the year and the month are changing in the loops, but the date (day of the month) stays set to the 1st.

Upvotes: 1

The wikipedia article you cited says

m is the month (3 = March, 4 = April, 5 = May, ..., 14 = February)

and

For January 1, 2000, the date would be treated as the 13th month of 1999,
so the values would be:
    q = 1
    m = 13
    K = 99
    J = 19

So you should probably adapt your input values accordingly, if you want to use this formula, i.e. add something like this

if (month <= 2) {
    month += 12;
    year--;
}

Upvotes: 2

Related Questions