[Coding Test]아날로그 시계

Author

SEOYEON CHOI

Published

January 9, 2025

- 링크

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

- 문제

시침, 분침, 초침이 있는 아날로그시계가 있습니다. 시계의 시침은 12시간마다, 분침은 60분마다, 초침은 60초마다 시계를 한 바퀴 돕니다. 따라서 시침, 분침, 초침이 움직이는 속도는 일정하며 각각 다릅니다. 이 시계에는 초침이 시침/분침과 겹칠 때마다 알람이 울리는 기능이 있습니다. 당신은 특정 시간 동안 알람이 울린 횟수를 알고 싶습니다.

알람이 울리는 횟수를 센 시간을 나타내는 정수 h1, m1, s1, h2, m2, s2가 매개변수로 주어집니다. 이때, 알람이 울리는 횟수를 return 하도록 solution 함수를 완성해주세요.

제한사항

0 ≤ h1, h2 ≤ 23

0 ≤ m1, m2 ≤ 59

0 ≤ s1, s2 ≤ 59

h1시 m1분 s1초부터 h2시 m2분 s2초까지 알람이 울리는 횟수를 센다는 의미입니다.

h1시 m1분 s1초 < h2시 m2분 s2초

시간이 23시 59분 59초를 초과해서 0시 0분 0초로 돌아가는 경우는 주어지지 않습니다.

h1, m1, s1, h2, m2, s2 = 23, 59, 50, 23, 59, 55
start_seconds = h1 * 3600 + m1 * 60 + s1
end_seconds = h2 * 3600 + m2 * 60 + s2
time_diff = end_seconds - start_seconds
def calculate_angles(h, m, s):
    hour_angle = (h % 12) * 30 + (m / 60) * 30 + (s / 3600) * 30
    min_angle = m * 6 + s * 0.1
    sec_angle = s * 6
    return hour_angle, min_angle, sec_angle

count = 0
hour_angle_new = -1
min_angle_new = -1
sec_angle_new = -1

for t in range(time_diff + 1):
    total_seconds = start_seconds + t
    h = (total_seconds // 3600) % 24
    m = (total_seconds % 3600) // 60
    s = total_seconds % 60

    hour_angle, min_angle, sec_angle = calculate_angles(h, m, s)
    
    if sec_angle_new != -1:
        if hour_angle_new == min_angle_new == sec_angle_new==0:
            count+=0
        elif sec_angle == hour_angle == min_angle:
                count +=1
        else:
            if (sec_angle_new < hour_angle <= sec_angle) or (sec_angle == 0 and sec_angle_new < hour_angle < 360):
                count +=1
            if (sec_angle_new < min_angle <= sec_angle) or (sec_angle == 0 and sec_angle_new < min_angle < 360):
                count +=1
    elif sec_angle_new == -1 and sec_angle == hour_angle == min_angle == 0:
        count +=1
        sec_angle = -1
        
    hour_angle_new, min_angle_new, sec_angle_new = hour_angle, min_angle, sec_angle
    print(f"시간: {h:02d}:{m:02d}:{s:02d}")
    print(f"  시침 각도: {hour_angle:.2f}도")
    print(f"  분침 각도: {min_angle:.2f}도")
    print(f"  초침 각도: {sec_angle:.2f}도")
    print(count)
    print("-" * 30)
# count
시간: 23:59:50
  시침 각도: 359.92도
  분침 각도: 359.00도
  초침 각도: 300.00도
0
------------------------------
시간: 23:59:51
  시침 각도: 359.93도
  분침 각도: 359.10도
  초침 각도: 306.00도
0
------------------------------
시간: 23:59:52
  시침 각도: 359.93도
  분침 각도: 359.20도
  초침 각도: 312.00도
0
------------------------------
시간: 23:59:53
  시침 각도: 359.94도
  분침 각도: 359.30도
  초침 각도: 318.00도
0
------------------------------
시간: 23:59:54
  시침 각도: 359.95도
  분침 각도: 359.40도
  초침 각도: 324.00도
0
------------------------------
시간: 23:59:55
  시침 각도: 359.96도
  분침 각도: 359.50도
  초침 각도: 330.00도
0
------------------------------

- 예제 문제는 다 맞으나, 제출하면 95%의 확률로 맞춤..

def solution(h1, m1, s1, h2, m2, s2):
    
    start_seconds = h1 * 3600 + m1 * 60 + s1
    end_seconds = h2 * 3600 + m2 * 60 + s2
    
    time_diff = end_seconds - start_seconds
    
    def calculate_angles(h, m, s):
        hour_angle = (h % 12) * 30 + (m / 60) * 30 + (s / 3600) * 30
        min_angle = m * 6 + s * 0.1
        sec_angle = s * 6
        return hour_angle, min_angle, sec_angle

    count = 0
    hour_angle_new = -1
    min_angle_new = -1
    sec_angle_new = -1

    for t in range(time_diff + 1):
        total_seconds = start_seconds + t
        h = (total_seconds // 3600) % 24
        m = (total_seconds % 3600) // 60
        s = total_seconds % 60

        hour_angle, min_angle, sec_angle = calculate_angles(h, m, s)

        if sec_angle_new != -1:
            if hour_angle_new == min_angle_new == sec_angle_new==0:
                count += 0
            elif sec_angle == hour_angle == min_angle:
                    count +=1
            else:
                if (sec_angle_new < hour_angle <= sec_angle) or (sec_angle == 0 and sec_angle_new < hour_angle <= 360):
                    count +=1
                if (sec_angle_new < min_angle <= sec_angle) or (sec_angle == 0 and sec_angle_new < min_angle <= 360):
                    count +=1
        elif sec_angle_new == -1 and sec_angle == hour_angle == min_angle:
            count +=1

        hour_angle_new, min_angle_new, sec_angle_new = hour_angle, min_angle, sec_angle

    answer = count
    return answer

- chatgpt 부탁 수정한 코드

def solution(h1, m1, s1, h2, m2, s2):
    start_seconds = h1 * 3600 + m1 * 60 + s1
    end_seconds = h2 * 3600 + m2 * 60 + s2
    
    time_diff = end_seconds - start_seconds
    
    def calculate_angles(h, m, s):
        hour_angle = (h % 12) * 30 + (m / 60) * 30 + (s / 3600) * 30
        min_angle = m * 6 + s * 0.1
        sec_angle = s * 6
        return hour_angle, min_angle, sec_angle

    count = 0
    hour_angle_new, min_angle_new, sec_angle_new = calculate_angles(h1, m1, s1)

    if hour_angle_new == min_angle_new == sec_angle_new == 0:
        count += 1

    for t in range(1, time_diff + 1):
        total_seconds = start_seconds + t
        h = (total_seconds // 3600) % 24
        m = (total_seconds % 3600) // 60
        s = total_seconds % 60

        hour_angle, min_angle, sec_angle = calculate_angles(h, m, s)

        if (sec_angle_new < min_angle_new and sec_angle >= min_angle) or (sec_angle_new < min_angle_new and sec_angle == 0):
            count += 1
            
        if (sec_angle_new < hour_angle_new and sec_angle >= hour_angle) or (sec_angle_new < hour_angle_new and sec_angle == 0):
            count += 1

        if sec_angle == hour_angle == min_angle == 0:
            count -= 1

        hour_angle_new, min_angle_new, sec_angle_new = hour_angle, min_angle, sec_angle

    return count

0시 5분 30초부터 0시 7분 0초까지 알람이 울린 횟수를 세는 예시입니다.

가장 짧은 바늘이 시침, 중간 길이인 바늘이 분침, 가장 긴 바늘이 초침입니다. 알람이 울리는 횟수를 세기 시작한 시각은 0시 5분 30초입니다. 이후 0시 6분 0초까지 초침과 시침/분침이 겹치는 일은 없습니다.

약 0시 6분 0.501초에 초침과 시침이 겹칩니다. 이때 알람이 한 번 울립니다. 이후 0시 6분 6초까지 초침과 시침/분침이 겹치는 일은 없습니다.

약 0시 6분 6.102초에 초침과 분침이 겹칩니다. 이때 알람이 한 번 울립니다. 이후 0시 7분 0초까지 초침과 시침/분침이 겹치는 일은 없습니다. 0시 5분 30초부터 0시 7분 0초까지는 알람이 두 번 울립니다. 이후 약 0시 7분 0.584초에 초침과 시침이 겹쳐서 울리는 세 번째 알람은 횟수에 포함되지 않습니다.

solution(0, 5, 30, 0, 7, 0)
# 2
2

12시 0분 0초부터 12시 0분 30초까지 알람이 울린 횟수를 세는 예시입니다.

알람이 울리는 횟수를 세기 시작한 시각은 12시 0분 0초입니다. 초침과 시침, 분침이 겹칩니다. 이때 알람이 한 번 울립니다. 이와 같이 0시 정각, 12시 정각에 초침과 시침, 분침이 모두 겹칠 때는 알람이 한 번만 울립니다.

이후 12시 0분 30초까지 초침과 시침/분침이 겹치는 일은 없습니다. 12시 0분 0초부터 12시 0분 30초까지는 알람이 한 번 울립니다.

solution(12, 0, 0, 12, 0, 30)
# 1
1

입출력 예 #3

0시 6분 1초부터 0시 6분 6초까지 초침과 시침/분침이 겹치는 일은 없습니다. 따라서 알람이 울리지 않으며 0을 return 해야 합니다.

solution(0, 6, 1, 0, 6, 6)
# 0
0

입출력 예 #4

11시 59분 30초부터 11시 59분 59초까지 초침과 시침/분침이 겹치는 일은 없습니다.

12시 0분 0초에 초침과 시침, 분침이 겹칩니다. 이때 알람이 한 번 울립니다.

11시 59분 30초부터 12시 0분 0초까지 초침과 시침/분침이 겹치는 횟수는 1이며 따라서 알람이 한 번 울립니다.

solution(11, 59, 30, 12, 0, 0)
# 1
1

입출력 예 #5

약 11시 58분 59.917초에 초침과 시침이 겹칩니다. 이때 알람이 한 번 울립니다. 11시 58분 59초부터 11시 59분 0초까지 초침과 시침/분침이 겹치는 횟수는 1이며 따라서 알람이 한 번 울립니다.

solution(11, 58, 59, 11, 59, 0)
# 1
1

입출력 예 #6

약 1시 5분 5.085초에 초침과 분침이 겹칩니다. 이때 알람이 한 번 울립니다. 약 1시 5분 5.424초에 초침과 시침이 겹칩니다. 이때 알람이 한 번 울립니다. 1시 5분 5초부터 1시 5분 6초까지 초침과 시침/분침이 겹치는 횟수는 2며 따라서 알람이 두 번 울립니다.

solution(1, 5, 5, 1, 5, 6)
# 2
2

입출력 예 #7

0시 0분 0초부터 23시 59분 59초까지 초침과 시침/분침이 겹치는 횟수는 2852며 따라서 알람이 총 2852번 울립니다.

solution(0, 0, 0, 23, 59, 59)
# 2852
2852

- 한 줄씩

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

시간 계산

start_seconds = h1 * 3600 + m1 * 60 + s1
end_seconds = h2 * 3600 + m2 * 60 + s2

time_diff = end_seconds - start_seconds
start_seconds, end_seconds, time_diff
(330, 420, 90)

각도 계산

def calculate_angles(h, m, s):
    hour_angle = (h % 12) * 30 + (m / 60) * 30 + (s / 3600) * 30
    min_angle = m * 6 + s * 0.1
    sec_angle = s * 6
    return hour_angle, min_angle, sec_angle

count 초기화

count = 0

처음 시각에서 값 계산

hour_angle_new, min_angle_new, sec_angle_new = calculate_angles(h1, m1, s1)

12:00:00 이거나 0:0:0 이면 count 추가

if hour_angle_new == min_angle_new == sec_angle_new == 0:
    count += 1
count
0

반복문 할 거

for t in range(1, time_diff + 1):
    total_seconds = start_seconds + t
    h = (total_seconds // 3600) % 24
    m = (total_seconds % 3600) // 60
    s = total_seconds % 60

약 0시 6분 0.501초에 초침과 시침이 겹칩니다

hour_angle_new, min_angle_new, sec_angle_new = calculate_angles(0, 6, 0)
h,m,s = 0,6,1
hour_angle, min_angle, sec_angle = calculate_angles(h, m, s)
hour_angle, min_angle, sec_angle
(3.0083333333333333, 36.1, 6)
if (sec_angle_new < min_angle_new and sec_angle >= min_angle) or (sec_angle_new < min_angle_new and sec_angle == 0):
    count += 1
count
0
if (sec_angle_new < hour_angle_new and sec_angle >= hour_angle) or (sec_angle_new < hour_angle_new and sec_angle == 0):
    count += 1
count
1
if sec_angle == hour_angle == min_angle == 0:
    count -= 1
count
1

약 0시 6분 6.102초에 초침과 분침이 겹칩니다

hour_angle_new, min_angle_new, sec_angle_new = calculate_angles(0, 6, 6)
h,m,s = 0,6,7
hour_angle, min_angle, sec_angle = calculate_angles(h, m, s)
hour_angle, min_angle, sec_angle
(3.058333333333333, 36.7, 42)
if (sec_angle_new < min_angle_new and sec_angle >= min_angle) or (sec_angle_new < min_angle_new and sec_angle == 0):
    count += 1
count
2
if (sec_angle_new < hour_angle_new and sec_angle >= hour_angle) or (sec_angle_new < hour_angle_new and sec_angle == 0):
    count += 1
count
2
if sec_angle == hour_angle == min_angle == 0:
    count -= 1
count
2

업데이트

hour_angle_new, min_angle_new, sec_angle_new = hour_angle, min_angle, sec_angle