[PCCP 기출문제] 3번 / 아날로그 시계

정민교·2024년 4월 18일
1
post-thumbnail

https://school.programmers.co.kr/learn/courses/30/lessons/250135

📒문제

주어진 시작 시간(h1 m1 s1)부터 주어진 종료 시간(h2 m2 s2)까지 시침과 초침, 분침과 초침이 겹치는 횟수를 구하라


h1, m1, s1 = 0, 5, 30
h2, m2, s2 = 0, 7, 0

📒풀이

매 초마다 '초' 가 '분' 혹은 '시' 와 같아지는 경우를 세는 경우라면 매우 간단하게 해결할 수 있다.(디지털 시계)

ex)

def solution(h1, m1, s1, h2, m2, s2):
    
    count = 0
    while (True):
        # 60초가 되면 분 올려주기
        if s1 >= 60:
            m1 += 1
            s1 = 0
        # 60분이 되면 시 올려주기
        if m1 >= 60:
            h1 += 1
            m1 = 0
        
        #현재 시간이 목표 시간이 되면 종료
        if h1 == h2 and m1 == m2 and s1 == s2:
            break   
        
        if s1 == m1 or s1 == h1 % 12:
            count += 1
            
        s1 += 1

    return count

하지만 이 문제는 아날로그 시계로 초침이 이동할 때마다 분침과 시침이 미세하게 조금씩 움직이는 경우이다.

✔️핵심

이런 경우라면 초마다 초침이 시침/분침을 지났는지만 검사하면 된다.
그러기 위해서 초마다 시침, 분침, 초침이 움직이는 각도를 구해서 초침이 시침/분침을 지났는지만 확인해주면 된다.

def solution(h1, m1, s1, h2, m2, s2):
    answer = 0

    # 시작시간과 끝시간을 초단위로 변환
    startTime = h1 * 3600 + m1 * 60 + s1
    endTime = h2 * 3600 + m2 * 60 + s2  

    # next기준으로 계산할거니 포함되지 않는 시작시간 00시, 12시 미리 카운팅
    if startTime == 0 * 3600 or startTime == 12 * 3600:
        answer += 1

    while startTime < endTime:
        # 시침 1시간 = 30도 -> 1초에 30/3600도 즉, 1/120도 이동
        # 분침 1분 = 6도 -> 1초에 6/60도 즉, 1/10도 이동
        # 초침 1초 = 6도 -> 1초에 6도 이동 
        hCurAngle = startTime / 120 % 360
        mCurAngle = startTime / 10 % 360
        sCurAngle = startTime * 6 % 360

        # 다음 위치가 360도가 아닌 0도로 계산되어 카운팅에 포함되지 않는 경우 방지
        # 이동했을 때 지나쳤거나 같아졌는지를 비교하는 것이므로 현재위치는 해줄 필요없음
        hNextAngle = 360 if (startTime + 1) / 120 % 360 == 0 else (startTime + 1) / 120 % 360
        mNextAngle = 360 if (startTime + 1) / 10 % 360 == 0 else (startTime + 1) / 10 % 360
        sNextAngle = 360 if (startTime + 1) * 6 % 360 == 0 else (startTime + 1) * 6 % 360

        if sCurAngle < hCurAngle and sNextAngle >= hNextAngle:
            answer += 1
        if sCurAngle < mCurAngle and sNextAngle >= mNextAngle:
            answer += 1
        # 시침/분침과 동시에 겹쳤을 때 중복카운팅 제외 
        if sNextAngle == hNextAngle and hNextAngle == mNextAngle:
            answer -= 1

        startTime += 1
    
    return answer

📒시간복잡도

O(endTime - startTime)

📒정리

검색해보지 않고는 풀지 못했음

lv2 문제라기엔 생각보다 어려움. 문제의 접근 방식은 빠르게 찾았으나, 그걸 어떤 방식으로 구현해야 할 지 떠오르지 않았음.

시계문제에서 각도를 고려하는 방법도 하나의 방법이라는 것을 깨달았음.

profile
백엔드 개발자

0개의 댓글