반응형

안녕하세요 밤샘공부입니다~

질문이 있으시면, 아래 오픈채팅방이나 메일로 보내주세요~

[백준 2884번 파이썬]

2시간 이내에 답변 드리겠습니다. 

 

오픈챗 링크 : https://open.kakao.com/o/srASNxef

메일 주소 : studying.all.night.1114@gmail.com

 

전달력을 높이기 위해 평어체를 사용하였습니다.

 


1. 문제 설명

 

 (1) 문제

 상근이는 매일 아침 알람을 듣고 일어난다. 알람을 듣고 바로 일어나면 다행이겠지만, 항상 조금만 더 자려는 마음 때문에 매일 학교를 지각하고 있다. 상근이는 모든 방법을 동원해보았지만, 조금만 더 자려는 마음은 그 어떤 것도 없앨 수가 없었다. 이런 상근이를 불쌍하게 보던 창영이는 자신이 사용하는 방법을 추천해 주었다. 바로 "45분 일찍 알람 설정하기"이다.
 이 방법은 단순하다. 원래 설정되어 있는 알람을 45분 앞서는 시간으로 바꾸는 것이다. 어차피 알람 소리를 들으면, 알람을 끄고 조금 더 잘 것이기 때문이다. 이 방법을 사용하면, 매일 아침 더 잤다는 기분을 느낄 수 있고, 학교도 지각하지 않게 된다.
현재 상근이가 설정한 알람 시각이 주어졌을 때, 창영이의 방법을 사용한다면, 이를 언제로 고쳐야 하는지 구하는 프로그램을 작성하시오.
 

 (2) 입력

  첫째 줄에 두 정수 H와 M이 주어진다. (0 ≤ H ≤ 23, 0 ≤ M ≤ 59) 그리고 이것은 현재 상근이가 설정한 놓은 알람 시간 H시 M분을 의미한다.
입력 시간은 24시간 표현을 사용한다. 24시간 표현에서 하루의 시작은 0:0(자정)이고, 끝은 23:59(다음날 자정 1분 전)이다. 시간을 나타낼 때, 불필요한 0은 사용하지 않는다.

 

 (3) 출력

  첫째 줄에 상근이가 창영이의 방법을 사용할 때, 설정해야 하는 알람 시간을 출력한다. (입력과 같은 형태로 출력하면 된다.)

 

 (4) 예제 

  ① 예시 1

   - 입력

10 10

   - 출력

9 25

 

 


2. 문제 해석 및 총평

 

   해당 문제는 특정 시간이 주어졌을 때 그 시간의 45분 전 시간을 출력하면 되는 문제이다. 얼핏보면 쉬워보일 수 있으나 생각해야할 경우의 수가 꽤 많다. 이를 단순히 머릿속으로만 생각하기에는 실수할 가능성이 매우 높으므로, '구조도'를 그려보아야 한다. 물론, 이런 문제가 익숙하다면 바로 시간 + 분 -> 분단위로 고친 뒤 나머지 연산을 이용하여 조건문 없이 해결할 수도 있다. 그러나, 일단은 구조도 부터 그려보도록 하자. 

 

 (1) 첫번째 풀이. 구조도 그리기

   구조도를 그릴 때 가장 먼저 쓸 질문은 무엇이 될까? 다시말해서, 우리가 이 문제에서 조건문을 써야하는 이유는 무엇일까?

바로, 주어진 시간의 '분'이 45분 이상인 것과 45분 미만인 것에 따라 45분 전의 '시간'이 달라지기 때문이다. 그러므로, 가장 첫번째 갈림길(질문)은 "주어진 시간이 45분 이상인가?"가 되어야 한다. 이후에는 전날로 넘어가는 케이스만 고려해주면 될듯하다.

 

[기본적인 구조도]

   이해가 되는가? 아마 (m+60-45) 부분이 잘 이해가 안될 수 있다. 예를 들어보면 쉬운데. 지금이 2시 20분이라고 해보자. 그러면 45분전은 몇시인가? 1시 -15분이 되는가? 그렇지 않다!

 

   2시 20분을 1시 80분이라 생각하자. (시간에서 60분을 빌려온 것으로 해석해도 좋다). 그러면 1시 80분의 45분전은 1시 35분이 되며, 1시 35분이 2시 20분의 45분 전 시간이 된다! 따라서 현재 시간이 45분 미만이라면 시간에서 60분을 빌려온 뒤 45를 빼주면 된다.

 

   그러나, 현재 시간이 0시라면 0에서 1을 빌려올 경우 -1이 되어버리므로 케이스를 하나 더 나눠 주어야 한다. 이런 관점에서 위 구조도를 보면 완벽히 이해될 것이다.

 

 

 (2) 두번째 풀이. 나머지 연산의 활용

    이번에는 조건문을 쓰지 않고 풀어보자. 어떻게 하면 좋을까? 가장 먼저 든 생각은 시간을 모조리 분으로 바꾸어 보자는 생각이다. 아래 그림을 살펴보자. 

[시간을 모조리 분 단위로!!]

   이렇게 분단위로 바꾼 뒤, 여기에서 45분을 빼준다. 그후에 다시 시간 : 분으로 바꾸어 주는 것이다.

[예제 1 - 45분 뺀 뒤 다시 시간으로!!]

 

[예제2 - 45분 뺀 뒤 다시 시간으로!!]

   위 방법대로 분으로 바꾼 뒤 45분을 빼주면 굳이 조건문을 쓰지 않고도 문제를 해결할 수 있다. 단, 세번째 예시에서는 조금 주의해줄 필요가 있는 것이. 0시 30분은 분 단위로 바꾸어도 30분이 된다. 이때 45를 빼주게 되면 문제가 하나 발생하는데, 30-45=-15(분) 이기 때문이다! 그러므로, -15분에 1440분(24시간)을 더해주어 1425분을 만들어 주어야 한다. 그래야 23시 45분이라는 결과가 나온다. 이는, 나머지 연산을 이용하면 손쉽게 해결할 수 있는데 수학적으로 나머지는 항상 양수여야 하기 때문이다. 따라서 -15분을 1440으로 나누었을 때의 나머지는 1425분이 된다. 그러므로 분단위 시간에서 30분을 뺀 뒤 1440으로 나눈 나머지 연산을 취해 주면, 양수인 분은 그대로 그 값을 가지게 되고 음수일 경우에만 1440이 더해지는 효과를 볼 수 있다. 자세한 내용은 아래 코드를 확인해보자. 

 

 


3. 코드

 

 (1) 구조도를 그대로 옮기기

#방식 1

x = int(input())
y = int(input())

if x > 0 :
    if y > 0 :
        print(1)
    else :
        print(4)
else :
    if y > 0 :
        print(2)
    else :
        print(3)

   처음에 그렸던 구조도를 그대로 코드로 옮겼다. 직관적이면서 가장 간편한 풀이이다. 하지만, 아래 풀이들도 여러분이 구사할 수 있었으면 하는 바램이다. 

 

 (2) 분 단위로 바꾼 뒤 나머지 연산 활용

#분 단위로 바꾼 뒤 나머지 연산 활용
h, m = map(int, input().split())

total_minute = h*60+m
answer = (total_minute - 45)%1440
print(answer//60, answer%60)

   방식 2의 논리구조를 그대로 코드로 옮겼다. 어떤가? 조건문을 쓰지 않고도 이 문제를 푼 사실이 재밌지 않은가!! answer 부분에서 1440으로 나머지 연산을 해준 이유는 음수가 나왔을 때 1440(24시간)을 더해줘야 하기 때문이다. (이를, 조건문을 이용하지 않고 나머지 연산을 활용해 우아하게 구현할 수 있다.)

 

 (3) 짧은 코드

#코드 줄이기
h, m = map(int, input().split())
print(((h*60+m-45)%1440)//60, ((h*60+m-45)%1440)%60)

 코드를 최대한 줄여 보았다. (비추천 풀이. just 학습용)

반응형