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)?
問 19 「日曜日の数え上げ」
次の情報が与えられている.
-
1900年1月1日は月曜日である.
-
9月, 4月, 6月, 11月は30日まであり, 2月を除く他の月は31日まである.
-
2月は28日まであるが, うるう年のときは29日である.
-
うるう年は西暦が4で割り切れる年に起こる. しかし, 西暦が400で割り切れず100で割り切れる年はうるう年でない.
20世紀(1901年1月1日から2000年12月31日)中に月の初めが日曜日になるのは何回あるか?

fn length_of_february(year: u16) -> u8 { if (year % 4 == 0 && year % 100 != 0) || year % 400 == 0 { 29 } else { 28 } } struct FirstDayOfMonth { year: u16, month: u8, day_count: u64, sunday_count: u32, } impl FirstDayOfMonth { fn new() -> Self { Self { year: 1900, month: 1, day_count: 0, sunday_count: 0, } } fn is_sunday(&self) -> bool { self.day_count % 7 == 6 } fn next_month(&mut self) { self.day_count += match self.month { 2 => length_of_february(self.year) as u64, 4 | 6 | 9 | 11 => 30, _ => 31, }; if self.month == 12 { self.year += 1; self.month = 1; } else { self.month += 1; } if self.year != 1900 && self.is_sunday() { self.sunday_count += 1; } } } fn main() { let mut cal = FirstDayOfMonth::new(); while !(cal.year == 2000 && cal.month == 12) { cal.next_month(); } let sum = cal.sunday_count; println!("{}", sum); assert_eq!(sum, 171); }
#[derive(PartialEq)] enum Weekday { Mon, Tue, Wed, Thu, Fri, Sat, Sun, } fn zeller_congruence(mut y: u32, mut m: u32, d: u32) -> Weekday { if m == 1 || m == 2 { m += 12; y -= 1; } let yd = y / 100; let ym = y % 100; match (d + (26 * (m + 1)) / 10 + ym + ym / 4 + yd / 4 + 5 * yd) % 7 { 0 => Weekday::Sat, 1 => Weekday::Sun, 2 => Weekday::Mon, 3 => Weekday::Tue, 4 => Weekday::Wed, 5 => Weekday::Thu, 6 => Weekday::Fri, _ => panic!(), } } fn main() { let mut sum = 0u32; for y in 1901u32..=2000 { for m in 1u32..=12 { let weekday = zeller_congruence(y, m, 1); if weekday == Weekday::Sun { sum += 1; } } } println!("{}", sum); assert_eq!(sum, 171); }