Problem 19
Counting Sundays
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)?
数星期日
下列信息是已知的,当然你也不妨自己再验证一下。
- 1900年1月1日是星期一。
- 三十天在九月中,
四六十一也相同。
剩下都是三十一,
除去二月不统一。
二十八天平常年,
多加一天在闰年。 - 闰年指的是能够被4整除却不能被100整除的年份,或者能够被400整除的年份。
在二十世纪(1901年1月1日到2000年12月31日)中,有多少个月的1号是星期天?
package projecteuler;
import org.junit.Test;
public class Prj19 {
/**
* 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)?
*/
@Test
public void test() {
System.out.println(Calculator.calculateSundays(new TmYear(1901, 1, 1),
new TmYear(2000, 12, 13)));
}
public static class Calculator {
public static int calculateSundays(TmYear start, TmYear end) {
int sundays = -1;
int remain = 2; // 1 is sunday
while (!start.equals(end)) {
if (start.day == 1 && remain == 1) {
sundays += 1;
}
start = start.add(TmUnit.DAY);
remain += 1;
if (remain > 7) {
remain = 1;
}
}
System.out.println("sundays=" + sundays);
return sundays;
}
public static boolean isLeapyear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
}
public static enum TmUnit {
DAY
}
public static class TmYear {
public static final int[] DAYS_LIST = { 0, 31, 28, 31, 30, 31, 30, 31,
31, 30, 31, 30, 31 };
public static final int[] DAYS_LEAP_LIST = { 0, 31, 29, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31 };
public int year;
public int month;
public int day;
public TmYear(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public TmYear() {
this(1900, 1, 1);
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return this.year + "-" + this.month + "-" + this.day;
}
public TmYear add(TmUnit unit) {
if (unit != TmUnit.DAY) {
return null;
}
TmYear tm = new TmYear(this.year, this.month, this.day);
int day = tm.day;
int month = tm.month;
int year = tm.year;
if ((!Calculator.isLeapyear(year) && day == DAYS_LIST[month])
|| (Calculator.isLeapyear(year) && day == DAYS_LEAP_LIST[month])) {
tm.day = 1;
if (month == 12) {
tm.month = 1;
tm.year += 1;
return tm;
} else {
tm.month += 1;
return tm;
}
} else {
tm.day += 1;
return tm;
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + day;
result = prime * result + month;
result = prime * result + year;
return result;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof TmYear)) {
return false;
}
TmYear other = (TmYear) obj;
if (day != other.day) {
return false;
}
if (month != other.month) {
return false;
}
if (year != other.year) {
return false;
}
return true;
}
}
}