project euler 19

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;
		}

	}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值