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

아날로그 시계

프로그래머스 문제

어느날 문득 프로그래머스를 보는데 완료한 사람 48명에 정답률이 6% 인 문제가 보여 굉장히 흥미로워서 도전하게되었다. 흥미롭게 도전하게하고 흥미롭게 무너질 뻔 헀지만 어떻게든 풀긴풀었다.

아날로그시계-1.png

문제 설명

문제는 간단하게 아날로그 시계를 구현하는 것이다. 특정 시간A 와 시간B가 주어지면 두 시간 사이에 시침과 분침이 만나는 횟수를 구하는 것이다.

흐름 파악

흐름 파악을 위해 꼬리에 꼬리를 무는 방식으로 접근하려한다.

시침, 분침, 초침의 각도는 어떻게 구할까?

  • 초침은 60초에 한 바퀴를 돈다.
  • 분침은 60분에 한 바퀴를 돈다.
  • 시침은 12시간에 한 바퀴를 돈다.

당연히 원의 각도는 360도이므로 초침은 6도, 분침은 6도, 시침은 30도씩 움직인다.

문제 설명을 보면 0시 6분 0.501 초에 초침과 시침이 겹친다고 하는데 검사를 어떻게 해야해?

시간A ~ 시간B 까지 0.001 초 단위를 증가시키면서 검사한다면 86,400,000 반복문을 돌아야한다. 이는 시간 초과가 발생할 것이다.

24 * 60 * 60 * 1000 = 86400000

그래서 다른 방안으로는 1초씩 증가하면서 딱 겹치거나 지나갔는지 여부를 검사하는 것이 방법이 된다.

겹쳤는지 여부는 어떻게 구할까?

1초가 지났을 때 이전 분침, 시침의 각도보다 현재 시침 각도가 커지면 겹쳤던 것이다.

풀이 코드

분명 이 코드로 통과했지만 말끔하게 풀지 못했다. 문제를 풀고 다른 사람 풀이를 보면 언제나 훨씬 좋은 코드가 보이는데 배울거 배우고 가감없이 공유해서 성장을 위한 노력을 해야겠다.

코드 라인이 길어졌지만 크게 보면

  • 1초 마다 시침, 분침, 초침 각도가 담긴 배열 생성
  • 1초 마다 시침, 분침, 초침 각도를 이전 각도와 비교하여 카운트
def calc_clock_angle(h, m, s):
    second_angle = 6 * s
    minute_angle = 6 * m + (s / 10)
    hour_angle = (30 * h + m * 0.5 + (s * (0.5 / 60))) % 360

    return hour_angle, minute_angle, second_angle


def increase_s(cur_h, cur_m, cur_s):
    cur_s += 1
    if cur_s == 60:
        cur_m += 1
        cur_s = 0

    if cur_m == 60:
        cur_h += 1
        cur_m = 0
    return cur_h, cur_m, cur_s


def decrease_s(cur_h, cur_m, cur_s):
    cur_s -= 1
    if cur_s < 0:
        cur_s = 59
        cur_m -= 1

    if cur_m < 0:
        cur_m = 59
        cur_h -= 1

    if cur_h < 0:
        cur_h = 23

    return cur_h, cur_m, cur_s


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

    clock_angles = []

    cur_h, cur_m, cur_s = h1, m1, s1
    h2, m2, s2 = increase_s(h2, m2, s2)

    while not (cur_h >= h2 and cur_m >= m2 and cur_s >= s2):
        clock_angles.append(((cur_h % 12, cur_m, cur_s), calc_clock_angle(cur_h % 12, cur_m, cur_s)))
        cur_h, cur_m, cur_s = increase_s(cur_h, cur_m, cur_s)

    for i, angle_info in enumerate(clock_angles):
        hms, angles = angle_info

        h_angle, m_angle, s_angle = angles
        if h_angle == 0 and m_angle == 0 and s_angle == 0:
            answer += 1
            continue

        if m_angle == s_angle:
            answer += 1

        if i == 0:
            continue

        before_s_angle = clock_angles[i - 1][1][2]
        if before_s_angle < h_angle < s_angle:
            answer += 1
            if hms[1] == 0 and hms[2] == 1:
                answer -= 1

        elif before_s_angle == 354 and before_s_angle < h_angle < 360:
            answer += 1

        if before_s_angle < m_angle < s_angle:
            answer += 1
            if hms[1] == 0 and hms[2] == 1:
                answer -= 1

        elif before_s_angle == 354 and before_s_angle < m_angle < 360:
            answer += 1

    return answer


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

print(solution(23, 59, 58, 23, 59, 59), 0)
print(solution(23, 59, 57, 23, 59, 59), 0)

print(solution(0, 58, 59, 0, 59, 1), 0)
print(solution(0, 58, 58, 0, 59, 1), 1)

print(solution(12, 0, 0, 12, 1, 1), 2)

print(solution(12, 0, 0, 12, 0, 30), 1)
print(solution(0, 5, 59, 0, 7, 0), 2)
print(solution(0, 5, 30, 0, 7, 0), 2)

print(solution(12, 0, 58, 12, 1, 1), 1)

print(solution(12, 0, 0, 12, 0, 30), 1)
print(solution(12, 0, 0, 12, 0, 59), 1)
print(solution(11, 58, 0, 11, 59, 0), 2)
print(solution(12, 58, 00, 12, 59, 0), 2)
print(solution(12, 58, 00, 12, 59, 5), 3)

print(solution(12, 00, 1, 12, 1, 1), 1)
print(solution(12, 00, 1, 12, 1, 2), 2)

print(solution(0, 5, 59, 0, 7, 0), 2)
print(solution(0, 5, 30, 0, 7, 0), 2)
print(solution(0, 5, 30, 0, 7, 1), 3)
print(solution(0, 5, 30, 0, 7, 2), 3)

print(solution(0, 6, 1, 0, 6, 6), 0)
print(solution(11, 59, 59, 12, 0, 0), 1)
print(solution(12, 00, 0, 12, 0, 1), 1)
print(solution(12, 00, 1, 12, 0, 2), 0)
print(solution(12, 00, 1, 12, 0, 59), 0)
print(solution(12, 00, 1, 12, 1, 0), 0)
print(solution(11, 59, 59, 12, 0, 30), 1)

print(solution(0, 0, 0, 11, 59, 59), 1426)
print(solution(0, 0, 0, 0, 0, 30), 1)
print(solution(1, 5, 5, 1, 5, 6), 2)
print(solution(11, 59, 30, 12, 0, 0), 1)

print(solution(0, 5, 30, 0, 7, 0), 2)
print(solution(12, 0, 0, 12, 0, 30), 1)
print(solution(0, 6, 1, 0, 6, 6), 0)
print(solution(11, 59, 30, 12, 0, 0), 1)
print(solution(11, 58, 59, 11, 59, 0), 1)
print(solution(1, 5, 5, 1, 5, 6), 2)
print(solution(0, 0, 0, 23, 59, 59), 2852)
print(solution(0, 0, 0, 12, 0, 0), 1427)

print(solution(0, 0, 0, 0, 0, 1), 1)
print(solution(12, 0, 0, 23, 59, 59), 1426)

firebase storage 용량 제한 및 type 제한하기

목표

로그인한 사용자만 파일 업로드 가능

파일 크기 10MB 제한

...

알고리즘 Lv2. [2024 카카오 윈터 인턴쉽] 도넛과 막대 그래프

도넛과 막대 그래프

NCloud LB & SourcePipeline 구축하기
tech collection 서비스 성능 개선하기
Selenium 복권 구매 자동화 만들어보기
디자인 패턴
책 리뷰
블로그 챌린지