computer science/algorithm

[프로그래머스] 아날로그 시계 - PCCP 기출문제 3번 | Python3 LV.2

oogg 2024. 3. 7. 15:00
728x90

Programmers LV.2 아날로그 시계 - PCCP 기출문제 3번 - Python3

문제 설명 

시침, 분침, 초침이 있는 아날로그시계가 있습니다. 시계의 시침은 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초로 돌아가는 경우는 주어지지 않습니다.

 

입출력 예 

 

 

입출력 예 설명

입출력 예 #4

  • 11시 59분 30초부터 11시 59분 59초까지 초침과 시침/분침이 겹치는 일은 없습니다.
  • 12시 0분 0초에 초침과 시침, 분침이 겹칩니다. 이때 알람이 한 번 울립니다.

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

 

 

입출력 예 #5

  • 약 11시 58분 59.917초에 초침과 시침이 겹칩니다. 이때 알람이 한 번 울립니다.

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

 

입출력 예 #6

  • 약 1시 5분 5.085초에 초침과 분침이 겹칩니다. 이때 알람이 한 번 울립니다.
  • 약 1시 5분 5.424초에 초침과 시침이 겹칩니다. 이때 알람이 한 번 울립니다.

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

 

입출력 예 #7

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

 

통과된 코드

def pos(type, h, m, s):
    if type == "hour":
        pos = h * 5 + m / 12 + s / 720
        pos = pos - 60 if pos >= 60 else pos
    elif type == "min":
        pos = m + s / 60
        pos = pos - 60 if pos >= 60 else pos
    elif type == "sec":
        pos = s - 60 if s >= 60 else s
    else:
        raise ValueError("Invalid type. Please use 'hour', 'min', or 'sec'.")

    return pos


def is_slower_and_same_than(h1, m1, s1, h2, m2, s2):
    if h1 > h2:
        return False
    if h1 == h2:
        if m1 > m2:
            return False
        if m1 == m2:
            if s1 > s2:
                return False
            return True
    return True


def one_sec_flow(h, m, s):
    s += 1
    if s == 60:
        s = 0
        m += 1
        if m == 60:
            m = 0
            h += 1
    return h, m, s


def solution(h1, m1, s1, h2, m2, s2):
    h, m, s = h1, m1, s1
    cnt = 1 if pos("hour", h, m, s) == pos("min", h, m, s) == pos("sec", h, m, s) else 0
    about_to_be_same = 0

    while is_slower_and_same_than(h, m, s, h2, m2, s2):
        cnt += about_to_be_same
        about_to_be_same = 0

        pos_h = pos("hour", h, m, s)
        pos_m = pos("min", h, m, s)
        pos_s = pos("sec", h, m, s)
        next_pos_h = pos("hour", h, m, s + 1)
        next_pos_m = pos("min", h, m, s + 1)
        next_pos_s = pos("sec", h, m, s + 1)

        if next_pos_h == next_pos_m == next_pos_s:
            about_to_be_same += 1
            print("hour and min: ", h, m, s, pos_h, pos_m, pos_s)
        else:
            if pos_h > pos_s and next_pos_h <= (60 if next_pos_s == 0 else next_pos_s):
                about_to_be_same += 1
                print("hour: ", h, m, s, pos_h, pos_m, pos_s)
            if pos_m > pos_s and next_pos_m <= (60 if next_pos_s == 0 else next_pos_s):
                about_to_be_same += 1
                print("min: ", h, m, s, pos_h, pos_m, pos_s)

        h, m, s = one_sec_flow(h, m, s)

    return cnt

 

풀이

우선 위 코드에 사용된 3가지 함수들에 대핸 간단히 설명하자면 다음과 같다.

 

1. pos(type, h, m, s): 현재 시각을 매개변수로 받아 type에 따라 (시침, 분침, 초침) 총 60칸으로 나뉘어진 시계 칸 위치 중 어디에 위치해 있는지를 계산한다.

2. is_slower_and_same_than(h1, m1, s1, h2, m2, s2): h1, m1, s1이 h2, m2, s2의 시간보다 느리거나 같은지 비교한다.

3. one_sec_flow(h, m, s): 1초 씩 증가하기 위해 사용됨

 

메인 코드의 풀이는 다음과 같다.

 

시간을 1초 씩 증가시키며 시침, 분침, 초침의 현재 위치 & 1초 뒤의 위치를 비교해 겹치는 횟수를 센다.

 

주의할 점은 아래와 같다.

  1. 시침, 분침, 초침이 모두 겹칠 경우에는 알림이 한 번만 울린다. 이에 1초 뒤 시침, 분침, 초침의 위치가 모두 같아지는지 확인해야 한다.
  2. 처음에 울릴 경우도 생각한다. (e.g. 12:00에 시작했을 때 바로 한 번 울림) 이에 처음 cnt 변수를 설정할 때, 시침, 분침, 초침의 위치가 모두 같다면 1로 아니라면 0으로 설정한다.
  3. 정수가 아니라 그 사이에 알림이 울릴 수 있기에, about_to_be_same 변수를 활용해 알림이 울리는 횟수를 센다.

초침과 시침 혹은 초침과 분침이 겹치는지 확인할 때는 (지금은 시침이 앞서 있지만) && (1초 뒤에는 초침이 앞서 있음) 로 확인한다.

 

실행 결과

테스트 1 통과 (57.34ms, 10.3MB)
테스트 2 통과 (68.17ms, 10.2MB)
테스트 3 통과 (19.72ms, 10.3MB)
테스트 4 통과 (58.48ms, 10.4MB)
테스트 5 통과 (1.66ms, 10.4MB)
테스트 6 통과 (28.63ms, 10.3MB)
테스트 7 통과 (70.56ms, 10.3MB)
테스트 8 통과 (64.22ms, 10.3MB)
테스트 9 통과 (90.17ms, 10.3MB)
테스트 10 통과 (97.77ms, 10.5MB)
테스트 11 통과 (45.96ms, 10.2MB)
테스트 12 통과 (9.29ms, 10.3MB)
테스트 13 통과 (123.17ms, 10.3MB)
테스트 14 통과 (78.57ms, 10.4MB)
테스트 15 통과 (0.03ms, 10.3MB)
테스트 16 통과 (45.01ms, 10.4MB)
테스트 17 통과 (47.26ms, 10.3MB)
테스트 18 통과 (10.67ms, 10.3MB)
테스트 19 통과 (162.55ms, 10.4MB)
테스트 20 통과 (158.61ms, 10.3MB)
채점 결과
정확성: 100.0
합계: 100.0 / 100.0
 

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

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

728x90