본문 바로가기

프로그래밍/알고리즘

[EP019] 윤년

반응형

1901년 1월부터 2000년 12월까지 중에서 1일이 일요일인 달의 갯수를 구하는 문제. 윤년을 구하는 조건이 주어지고, 그 조건만 잘 써 주고, mod 7을 이용하면 요일을 구할 수 있다.

// leap_year.cpp : Defines the entry point for the console application.
//

/*
http://projecteuler.net
*____________________________________________________________________
Problem 19
14 June 2002

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

*/


#include "stdafx.h"

typedef enum {
	SUN = 0,
	MON,
	TUE,
	WED,
	THU,
	FRI,
	SAT
} YOIL;

#define DAYSOFWEEK 7

int daysOfMonth(int month, int year)
{
	int daysArray[] = { 
		31,  0, 31, 30, 31, 30,
		31, 31, 30, 31, 30, 31 
	};
	if (month == 1) {
		if (year % 4 == 0 && !(year % 100 == 0 && year % 400 != 0)) {
			return 29;
		}
		else {
			return 28;
		}
	}

	return daysArray[month];
}

int main(int argc, char* argv[])
{
	YOIL yoil;
	int year, month;
	int cnt = 0;

	yoil = MON;
	year = 1900;
	month = 0; // 1월

	while (year < 2001) {
		yoil = (YOIL)(((int)yoil + daysOfMonth(month, year)) % DAYSOFWEEK);
		if (month == 11)
		{
			month = 0;
			year++;
		}
		else {
			month++;
		}
		if (yoil == 0 && year > 1900)
			cnt++;
	}
	printf("%d", cnt);

	return 0;
}

파이썬의 datetime 모듈을 사용하여 다음과 같이 간단하게 할 수도 있다. 간단히 설명하면, 1. 1901년 1월 부터 2000년 12월까지 모든 월의 첫번째 날에 대한 date 객체를 생성한다. 2. 이 date 객체에서 weekday() 메소드로 요일을 확인하여 일요일인 것만 필터링한다. 3. 그 갯수를 확인한다.

import datetime

firstdays = [ datetime.date(y, m, 1) for y in range(1901, 2001) for m in range(1, 13) ]
sunday_firstdays = [ d for d in firstdays if d.weekday() == 6 ]
print(len(sunday_firstdays))
# 171
728x90