Reputation: 343
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
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
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
Reputation: 6308
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