프로그래머스 - 2016년
구해야 하는 것
- 2016년 a월 b일이 무슨 요일인지 구하라
주어진 자료
- 2016년 1월 1일은 금요일
- a = 월, b = 일
- 요일의 이름은 SUN, MON, TUE, WED, THU, FRI, SAT(일요일부터 토요일까지)
조건
- 2016년은 윤년이다.
- a월 b일은 실제로 있는 날이다.
숨겨진 조건이나 자료
- 윤년이므로 2월은 29일까지 있다.
- 1, 3, 5, 7, 8, 10, 12월은 31일까지 있고, 4, 6, 9, 11월은 30일까지 있다.
계획
일단 규칙을 먼저 찾아보자
만약 1월 24일의 요일을 구한다고 하면,
- 24 % 7 = 3
- 3에서 1일을 빼주면 = 2
- 1월 1일은 금요일이므로 24일은 2일 뒤인 일요일이다.
만약 1월 28일의 요일을 구한다고 하면,
- 28 % 7 = 0
- 0에서 1일을 빼주면 = -1
- 1월 1일은 금요일이므로 28일은 1일 전인 목요일이다.
만약 2월 15일의 요일을 구한다고 하면,
- 2월 15일은 1월 46일이라고 할 수 있다.(31 + 15)
- 46 % 7 = 4
- 4에서 1일을 빼주면 = 3
- 1월 1일은 금요일이므로 2월 15일은 3일 뒤인 월요일이다.
이제 규칙을 찾았으니 계획을 세워보자
- 각 달이 몇일까지 있는지를 배열 month에 저장해 놓는다.
- 요일을 배열 day에 저장해놓는다. 이때 SUN부터 SAT까지의 순서로 저장한다.
- 금요일이 저장돼있는 인덱스인 5를 fridayIndex에 저장해놓는다.(굳이 저장해놓지 않아도 되긴 함)
- 배열 month를 이용해서 b에 (a - 1)월까지의 일 수를 모두 더한다.
- move에 b % 7을 저장한다.
- move를 1 감소시킨다.
- day[fridayIndex에 + move]가 구하고 싶은 요일에 해당하는데, 만약 move가 2 이상인 경우에는 day의 인덱스 범위를 벗어나게 된다.
ex) move가 3일 경우 day[8]이 되어 인덱스 범위를 벗어나는데, 정답은 금요일의 3일 뒤인 월요일(day[1])이 되어야 한다.
move가 6일 경우 day[10]이 되어 인덱스 범위를 벗어나는데, 정답은 금요일의 6일 뒤인 목요일(day[4])이 되어야 한다.
이를 통해 move가 2 이상인 경우에는 day[move - 2]가 정답 요일이라는 것을 알 수 있다. - 따라서 move가 2 이상이면 answer에 day[move - 2]를 저장하고, 그렇지 않으면 day[fridayIndex + move]를 저장한 후 answer를 return 한다.
실행
string solution(int a, int b) {
int month[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
string day[7] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
int fridayIndex = 5;
int move;
string answer = "";
// (a - 1)월까지의 일 수를 모두 더하기
for(int i = 0; i < a - 1; i++) {
b += month[i];
}
// day 배열에서 얼만큼 이동할지 구하기
move = b % 7;
move--;
if(move >= 2) { // fridayIndex + move가 day의 인덱스 범위를 벗어날 때
answer = day[move - 2];
}
else {
answer = day[move + fridayIndex];
}
return answer;
}
반성
- 4.까지의 과정 후에 {b + (fridayIndex - 1)} % 7을 하면 인덱스 범위에 대한 별도의 처리 과정 없이 바로 요일의 인덱스를 구할 수 있다.
- 계획 중 move를 1 감소시키는 과정이 있는데, 사실 명확한 이유가 있는 게 아니라 뭔가 느낌상 1일을 빼줘야 할 것 같았다. 그래서 다른 사람의 풀이를 찾아보니까 1월 1일이 하루가 지난날이 아니기 때문에 빼는 거라고 한다.
문제 풀 때 모든 계획에 대해서 왜 그래야 하는지를 꼭 짚고 넘어가도록 해야겠다.