문제 링크
https://www.acmicpc.net/problem/2884
정답 코드는 아래와 같습니다.
1
2
3
4
5
|
H, M = [int(x) for x in input().split()]
T = ((H * 60 + M - 45) + (24*60)) % (24*60)
M = T % 60
H = T // 60
print(H, M)
|
cs |
간단한 문제이면서도 중요한 내용을 담고 있는 문제입니다.
첫 번째는 단위 환산 또는 진수 변환입니다.
어떤 값의 단위가 복잡한 경우에는 가장 낮은 단위로 환산하여 계산을 하고 다시 복잡한 단위로 변환하는 것이죠.
이 문제에서는 시간을 시(H)와 분(M) 으로 주는데요. 이것을 (문제 조건에서) 가장 낮은 단위인 분으로 변환하고 계산을 완료한 이후에 다시 시와 분으로 환산하여 답을 출력해주게 됩니다.
이것은 결국 진수 변환과 같은 문제인 것을 알 수 있는데요.
분으로 주어진 값을 시와 분으로 환산하는 것은 10진수를 60진수로 변환하는 것이고,
시와 분으로 주어진 값을 분으로 환산하는 것은 60진수를 10진수로 변환하는 것입니다.
두 번째는 오버/언더 플로우 입니다.
하루라는 시간의 범위는 분으로 환산한 경우 0 부터 24 * 60 - 1 사이의 값만을 가져야 하는데,(경계 포함)
이 범위를 벗어나는 값이 들어오는 경우 어떻게 처리할 수 있는가에 대한 이야기 입니다.
문제에서 상근이는 알람시계를 거꾸로 돌리기 때문에 이 문제는 언더플로우가 발생할 수 있습니다.
(H * 60 + M - 45 값이 음수일 수 있다는 뜻입니다)
가장 쉽게 생각할 수 있는 해결방안은, H * 60 + M - 45 값을 확인하고 경우에 따라 다르게 처리하는 것입니다.
한 마디로 아래와 같이 if 문으로 처리하는 것이지요. (참고로 이 코드도 제출하면 문제 없이 통과합니다)
1
2
3
4
5
6
7
|
H, M = [int(x) for x in input().split()]
T = H * 60 + M - 45
if T < 0:
T += 24 * 60
M = T % 60
H = T // 60
print(H, M)
|
cs |
이 문제의 경우에는 이렇게 작성하여도 큰 문제가 없습니다. 왜냐하면 이 코드는 단 한 번만 실행되기 때문입니다.
하지만 만일 이 코드가 빈번하게 호출된다면 이야기가 조금 달라집니다.
그 이유는 if 문은 연산 속도가 상당히 느리기 때문입니다. (이 표현은 사실 정확한 표현이 아니지만 쉬운 이해를 위하여 이렇게 표현하였습니다.)
따라서 고급(?) 개발자들은 이런 오버/언더플로우를 처리하는데, if 문을 사용하지 않으려고 합니다.
그리고 제가 사용한 방법은 언더플로우를 막기 위해서 흔히 사용되는 방법입니다.
언더플로우를 처리하는 방법은 대상 값(x) 에다가 범위(n) 을 더하고 그 값을 n 으로 나눈 나머지를 취하는 것입니다.
식으로 표현하자면 다음과 같습니다.
1
|
(x + n) % n
|
cs |
이 문제에서는 x 가 H * 60 + M - 45 이고, n 이 24 * 60 인 것입니다.
오버플로우를 막으려면 어떻게 해야할지는 직접 한 번 생각해보시기 바랍니다.
이 문제에 대한 이야기는 아니지만,
어떤 플랫폼에서든 절댓값 함수(abs)를 제공하는 경우, 보통 if 문을 사용하지 않는 방식으로 구현되어 있습니다.
따라서 어떤 플랫폼에서 abs 함수를 제공해준다면 if 문을 이용하여 직접 구현하지 말고 제공되는 api 를 사용하는 것을 권합니다.
abs 함수가 어떻게 if 문을 사용하지 않고 구현하였을지 생각 및 확인해보시는 것도 재미있을 것 같습니다.
if 문의 속도가 느린 것에 대한 내용은 정확하게 설명하자면 cpu pipeline 부터 설명을 해야 하기 때문에 너무 내용이 방대해지므로 이번 글에서는 다루지 않겠습니다만, 추후에 기회가 된다면 이야기 하도록 하겠습니다.
풀이는 아래 영상을 참고 바랍니다.
https://www.youtube.com/watch?v=mizdvdnhuyk
저작권 라이선스: CC BY (출처만 표시하면 자유롭게 이용 가능)
'백준(BOJ) 문제 풀이' 카테고리의 다른 글
백준 2920번 문제(음계) 파이썬(Python) 풀이 [로밍맨] (0) | 2021.07.12 |
---|---|
백준 2908번 문제(상수) 파이썬(Python) 풀이 [로밍맨] (0) | 2021.07.10 |
백준 2753번 문제(윤년) 파이썬(Python) 풀이 [로밍맨] (0) | 2021.07.07 |
백준 2748번 문제(피보나치 수 2) 파이썬(Python) 풀이 [로밍맨] (0) | 2021.07.07 |
백준 2742번 문제(기찍 N) 파이썬(Python) 풀이 [로밍맨] (0) | 2021.07.06 |