문제설명
2016년 1월 1일은 금요일입니다. 2016년 a월 b일은 무슨 요일일까요? 두 수 a ,b를 입력받아 2016년 a월 b일이 무슨 요일인지 리턴하는 함수, solution을 완성하세요. 요일의 이름은 일요일부터 토요일까지 각각
SUN,MON,TUE,WED,THU,FRI,SAT
입니다. 예를 들어 a=5, b=24라면 5월 24일은 화요일이므로 문자열 "TUE"를 반환하세요.제한사항
- 2016년은 윤년입니다.
- 2016년 a월 b일은 실제로 있는 날입니다. (13월 26일이나 2월 45일같은 날짜는 주어지지 않습니다)
입출력 예
a b result 5 24 "TUE" 출처: 프로그래머스 코딩 테스트 연습, https://school.programmers.co.kr/learn/challenges
문제가 2016년 1월 1일은 금요일이고 2016년은 윤년이라는 힌트를 줬기 때문에
크게 어렵지는 않을거라 생각했는데 날짜 구하는 공식같은걸 아예 몰라서
이것저것 많이 찾아봤다. 그 중에 둠스데이 알고리즘
이라는 것도 있었다.
실무였으면 Date
클래스 등으로 해결 했겠지만 테스트 의미가 없으니
최대한 생각을 많이 해보려고 노력했다.
둠스데이 알고리즘
을 좀 보고 시도해보려 했는데, 뭔 얘긴지 이해가 잘 안됐다.
그래서 엑셀에 날짜를 쭉 찍어놓고 어떤 규칙성이 있는지 찾아봤다.
a월 b일이 기준일인 2016년 1월 1일 금요일부터 며칠이 지났는지 구하고,
그걸 7로 나눈 나머지로 무슨 요일인지 알 수 있다.
class Solution {
public String solution(int a, int b) {
String[] day = {"FRI", "SAT", "SUN", "MON", "TUE", "WED", "THU"};
// 윤년의 일 수
int[] month = {31,29,31,30,31,30,31,31,30,31,30,31};
int count = -1; // 0~365일
for (int i=0; i<a-1; i++) {
count += month[i];
}
return day[(count+b)%7];
}
}
가장 낮은값인 1월 1일이 들어올 경우 기준일로부터 0일,
day[0]
일 경우는 "FRI"로 잡아줘야 하니 day
의 시작을 금요일부터, count
는 -1부터 시작했다.
간단했지만 생각을 오래한 문제였다.
둠스데이 알고리즘(Doomsday algorithm)은 존 호턴 콘웨이가 발명한 알고리즘으로, 임의의 날짜에 해당하는 요일을 쉽게 구하는 데에 쓰인다.
한 해에서 다음 날짜는 언제나 요일이 같다.
이것은 일과 월이 모두 4부터 12사이의 짝수로 되어 있으므로 외우기 쉽다. 한편, 다음과 같은 날들도 위의 날짜들과 요일이 같다.
(이것은 흔히 'nine-to-five', 'seven-eleven'이라고 외운다.)
그리고 1월과 3월은 다음 날짜를 사용한다.
이와 같이 한 해에서 요일이 같은 날들을 일컬어 둠스데이(Doomsday)라고 한다. 이 날짜와 그 해의 둠스데이의 요일만 기억하고 있으면, 날짜에 따른 요일을 쉽게 구할 수 있다.
어떤 한 날과 다른 한 날의 요일이 같으려면, 그 두 날 사이의 날짜 차이가 7의 배수여야 한다. 예를 들어서 1월 1일과 1월 8일, 1월 15일은 같은 요일이라는 것을 쉽게 알 수 있다.
앞에서 4월 4일과 6월 6일은 63일 차이가 나며, 6월 6일과 8월 8일 역시 63일 차이가 난다. 이와 같이, 한 해 안에서 요일이 서로 같은 둠스데이의 날짜 차이 역시 7의 배수이다. 둠스데이는 한 해 안에서 항상 요일이 같은 날들, 예를 들자면 1월 1일과 1월 8일 같은 날들 중 사람들이 기억하기 쉬운 날짜를 선택해서 만든 날들이다.
출처 : 위키백과 - 둠스데이 알고리즘 문서