알고리즘/백준 BOJ

[백준] 1476: 날짜 계산 (Python)

한비 2022. 3. 27. 20:33
반응형

1476: 날짜 계산

문제

준규가 사는 나라는 우리가 사용하는 연도와 다른 방식을 이용한다. 준규가 사는 나라에서는 수 3개를 이용해서 연도를 나타낸다. 각각의 수는 지구, 태양, 그리고 달을 나타낸다.

지구를 나타내는 수를 E, 태양을 나타내는 수를 S, 달을 나타내는 수를 M이라고 했을 때, 이 세 수는 서로 다른 범위를 가진다. (1 ≤ E ≤ 15, 1 ≤ S ≤ 28, 1 ≤ M ≤ 19)

우리가 알고있는 1년은 준규가 살고있는 나라에서는 1 1 1로 나타낼 수 있다. 1년이 지날 때마다, 세 수는 모두 1씩 증가한다. 만약, 어떤 수가 범위를 넘어가는 경우에는 1이 된다.

예를 들어, 15년은 15 15 15로 나타낼 수 있다. 하지만, 1년이 지나서 16년이 되면 16 16 16이 아니라 1 16 16이 된다. 이유는 1 ≤ E ≤ 15 라서 범위를 넘어가기 때문이다.

E, S, M이 주어졌고, 1년이 준규가 사는 나라에서 1 1 1일때, 준규가 사는 나라에서 E S M이 우리가 알고 있는 연도로 몇 년인지 구하는 프로그램을 작성하시오.

입력

첫째 줄에 세 수 E, S, M이 주어진다. 문제에 나와있는 범위를 지키는 입력만 주어진다.

출력

첫째 줄에 E S M으로 표시되는 가장 빠른 연도를 출력한다. 1 1 1은 항상 1이기 때문에, 정답이 음수가 나오는 경우는 없다.

풀이

 문제를 파악한 직후에 전체 경우의 수가 15*28*19이므로 브루트 포스로 해결할 수 있음을 확인한 후 3차원 리스트를 이용해 해결하기로 했다. 습관적으로 리스트에 맞게 3중 for문을 썼는데 준규의 연도와 우리가 사용하는 연도를 어떻게 매칭하면 좋을지 감이 오지 않았다. 그래서 1 1 1부터 하나씩 경우를 나열해보니 E, S, M에 대한 인덱스를 따로 두어 1씩 증가시키고 각자 최댓값에 도달하면 다시 1로 초기화하면 된다는 아이디어가 떠올랐다.

 처음에는 while문을 쓰기로 하고 코드의 토대를 짰으나 코드가 너무 긴데다가 인덱스 에러가 나면서 코드가 제대로 작동하지 않았다. 다시 for문으로 수정하였는데도 인덱스 에러가 계속 나서 중간에 print문을 삽입해 확인해보니 k == 20을 k == 28로 오타낸 것이었다. 오타에 항상 주의하도록 하자. 그렇게 해서 처음 정답 판정을 받은 코드는 다음과 같다.

# 1476: 500 - 브루트 포스 - 날짜 계산
E, S, M = map(int, input().split())
year = [[[0]*20 for j in range(29)] for i in range(16)]
max = 15*28*19
i, j, k = 1, 1, 1
for result in range(1, max+1):
    year[i][j][k] = result
    i += 1
    j += 1
    k += 1
    if i == 16:
        i = 1
    if j == 29:
        j = 1
    if k == 20:
        k = 1
    if year[E][S][M] != 0:
        break
print(year[E][S][M])

 정답 판정을 받긴 했으나 파이썬치고 코드가 너무 길다는 생각이 들어 리팩토링할 방법을 고민하게 되었다. 다른 사람들의 코드를 참고하여 생각해본 결과 우선 max 변수가 무의미하다는 것을 깨달았다. for문을 사용할거라면 max변수의 값이 필요하지만 어차피 가장 빠른 연도를 출력하는 것이므로 while문으로 무한루프를 돌리다 원하는 값을 찾으면 반복문을 정지하면 된다. 그리고 또 한 가지 깨달은 것은 굳이 리스트에 값을 저장할 필요가 없다는 것이다. 직전에 다이나믹 프로그래밍 문제를 풀던 습관이 남아있어서 dp테이블을 만들듯이 자꾸 리스트에 값을 저장하게 되는데, 원하는 값을 구하고 나면 해당 값을 출력하고 프로그램을 종료하면 되므로 굳이 year리스트에 값을 저장할 필요가 없다. 그 외에도 세미콜론을 이용해 i+=1, j+=1, k+=1 등의 짧은 식은 한 줄에 넣어 간결하게 표현할 수 있었다. 그렇게 수정한 코드는 다음과 같다.

# 1476: 500 - 브루트 포스 - 날짜 계산
E, S, M = map(int, input().split())
i, j, k, count = 1, 1, 1, 1
while(1):
    if i == E and j == S and k == M:
        print(count)
        break
    i += 1; j += 1; k += 1; count += 1
    if i == 16: i = 1
    if j == 29: j = 1
    if k == 20: k = 1
반응형