본문 바로가기
Programming Practice/Python

프로그래머스 <PCCP 기출문제 1번 / 동영상 재생기> Python

by TAMIK 2025. 4. 18.
728x90

Programmers <PCCP 기출문제 1번 / 동영상 재생기> 문제

문제 설명

당신은 동영상 재생기를 만들고 있습니다. 당신의 동영상 재생기는 10초 전으로 이동, 10초 후로 이동, 오프닝 건너뛰기 3가지 기능을 지원합니다. 각 기능이 수행하는 작업은 다음과 같습니다.

10초 전으로 이동: 사용자가 "prev" 명령을 입력할 경우 동영상의 재생 위치를 현재 위치에서 10초 전으로 이동합니다. 현재 위치가 10초 미만인 경우 영상의 처음 위치로 이동합니다. 영상의 처음 위치는 0분 0초입니다.

10초 후로 이동: 사용자가 "next" 명령을 입력할 경우 동영상의 재생 위치를 현재 위치에서 10초 후로 이동합니다. 동영상의 남은 시간이 10초 미만일 경우 영상의 마지막 위치로 이동합니다. 영상의 마지막 위치는 동영상의 길이와 같습니다.

오프닝 건너뛰기: 현재 재생 위치가 오프닝 구간(op_start ≤ 현재 재생 위치 ≤ op_end)인 경우 자동으로 오프닝이 끝나는 위치로 이동합니다.


동영상의 길이를 나타내는 문자열 video_len, 기능이 수행되기 직전의 재생위치를 나타내는 문자열 pos, 오프닝 시작 시각을 나타내는 문자열 op_start, 오프닝이 끝나는 시각을 나타내는 문자열 op_end, 사용자의 입력을 나타내는 1차원 문자열 배열 commands가 매개변수로 주어집니다. 이때 사용자의 입력이 모두 끝난 후 동영상의 위치를 "mm:ss" 형식으로 return 하도록 solution 함수를 완성해 주세요.



제한사항
video_len의 길이 = pos의 길이 = op_start의 길이 = op_end의 길이 = 5
    video_len, pos, op_start, op_end는 "mm:ss" 형식으로 mm분 ss초를 나타냅니다.
    0 ≤ mm ≤ 59
    0 ≤ ss ≤ 59
    분, 초가 한 자리일 경우 0을 붙여 두 자리로 나타냅니다.
    비디오의 현재 위치 혹은 오프닝이 끝나는 시각이 동영상의 범위 밖인 경우는 주어지지 않습니다.
    오프닝이 시작하는 시각은 항상 오프닝이 끝나는 시각보다 전입니다.
1 ≤ commands의 길이 ≤ 100
    commands의 원소는 "prev" 혹은 "next"입니다.
    "prev"는 10초 전으로 이동하는 명령입니다.
    "next"는 10초 후로 이동하는 명령입니다.



입출력 예
video_len      pos         op_start         op_end                    commands                    result
"34:33"      "13:00"        "00:55"         "02:55"                   ["next", "prev"]                "13:00"
"10:55"       "00:05"        "00:15"        "06:55"              ["prev", "next", "next"]         "06:55"
"07:22"       "04:05"       "00:15"         "04:07"                       ["next"]                        "04:17"




입출력 예 설명
입출력 예 #1
시작 위치 13분 0초에서 10초 후로 이동하면 13분 10초입니다.13분 10초에서 10초 전으로 이동하면 13분 0초입니다.따라서 "13:00"을 return 하면 됩니다.

입출력 예 #2
시작 위치 0분 5초에서 10초 전으로 이동합니다. 현재 위치가 10초 미만이기 때문에 0분 0초로 이동합니다.0분 0초에서 10초 후로 이동하면 0분 10초입니다.0분 10초에서 10초 후로 이동하면 0분 20초입니다. 0분 20초는 오프닝 구간이기 때문에 오프닝이 끝나는 위치인 6분 55초로 이동합니다. 따라서 "06:55"를 return 하면 됩니다.

입출력 예 #3
시작 위치 4분 5초는 오프닝 구간이기 때문에 오프닝이 끝나는 위치인 4분 7초로 이동합니다. 4분 7초에서 10초 후로 이동하면 4분 17초입니다. 따라서 "04:17"을 return 하면 됩니다.

def solution(video_len, pos, op_start, op_end, commands):
    answer = ''
    video_n = sum(int(x) * m for x, m in zip(video_len.split(":"), [60, 1]))
    pos_n = sum(int(x) * m for x, m in zip(pos.split(":"), [60, 1]))
    op_start_n = sum(int(x) * m for x, m in zip(op_start.split(":"), [60, 1]))
    op_end_n = sum(int(x) * m for x, m in zip(op_end.split(":"), [60, 1]))

    for command in commands:
        if 0 <= pos_n <= video_n:
            if op_start_n <= pos_n <= op_end_n:
                pos_n = op_end_n
            if command == "prev":
                pos_n -= 10
                if pos_n < 0:
                    pos_n = 0
                if op_start_n <= pos_n <= op_end_n:
                    pos_n = op_end_n
            elif command == "next":
                pos_n += 10
                if pos_n > video_n:
                    pos_n = video_n
                if op_start_n <= pos_n <= op_end_n:
                    pos_n = op_end_n
    answer = f'{pos_n // 60):02d}:{pos_n % 60:02d}'
    # answer = '{:02d}:{:02d}'.format(pos_n // 60, pos_n % 60)

    return answer

 

 

 

    video_n = sum(int(x) * m for x, m in zip(video_len.split(":"), [60, 1]))
    pos_n = sum(int(x) * m for x, m in zip(pos.split(":"), [60, 1]))
    op_start_n = sum(int(x) * m for x, m in zip(op_start.split(":"), [60, 1]))
    op_end_n = sum(int(x) * m for x, m in zip(op_end.split(":"), [60, 1]))

    
    매개 변수들을 ':'을 기준으로 나눠서 초단위로 변환 시켜준다.
    : 앞쪽은 분이기 때문에 분*60, 뒤쪽은 초이기 때문에 그대로 초*1

split을 활용하여 나눠주고 zip으로 한 번에 묶어서 나타내줬다. map을 이용해도 괜찮음.

	for command in commands:
        if 0 <= pos_n <= video_n:
            if op_start_n <= pos_n <= op_end_n:
                pos_n = op_end_n
            if command == "prev":
                pos_n -= 10
                if pos_n < 0:
                    pos_n = 0
                if op_start_n <= pos_n <= op_end_n:
                    pos_n = op_end_n
            elif command == "next":
                pos_n += 10
                if pos_n > video_n:
                    pos_n = video_n
                if op_start_n <= pos_n <= op_end_n:
                    pos_n = op_end_n

for문을 돌면서 commands의 요소들을 순회.

prev를 했을 때 00:00을 넘어갈 수도 있고, next를 했을 때 video_n을 넘어갈 수도 있기 때문에,

각각의 조건에 0보다 작아질 때와, 영상 길이보다 커질 때 조건을 추가하여 이상하게 계산되는 것을 막아준다.

0보다 작아지면 0으로, 영상 길이보다 커지면 영상 길이만큼으로.

 

    answer = f'{pos_n // 60:02d}:{pos_n % 60:02d}'
    # answer = '{:02d}:{:02d}'.format(pos_n // 60, pos_n % 60)

answer문자열에 f_string을 사용하여 값을 00:00형식으로 넣어준다.

pos_n을 초단위로 바꿨기 때문에 다시 분+초로 만들기 위하여 앞쪽에는 몫이 float으로 나오는 것을 막기 위해 pos_n/60을 int형으로 형변환 해 주던지 pos_n//60 해주기. 뒤쪽에는 나머지가 나오기 때문에 소수점 나올 일 없어서 바로 형식만 지정.

주의 :

    answer = f'{pos_n // 60:02d}:{pos_n % 60:02d}'	#정답
    answer = f'{pos_n // 60 : 02d}:{pos_n % 60 : 02d}'	#오류

':'옆에 공백을 만들지 말자. 오류난다.

 

    answer = '{:02d}:{:02d}'.format(pos_n // 60, pos_n % 60)

f_string말고 format을 사용하면 이렇게 표현 가능.

 

 

 


다 풀고 다른 사람들 답안을 훑어보니 추상화/모듈화 해서 푼 사람들이 많길래 나도 개선 시도

def solution(video_len, pos, op_start, op_end, commands):
    def to_seconds(t_str):
        m, s = map(int, t_str.split(":"))
        return m * 60 + s

    def to_string(seconds):
        return f'{seconds // 60:02d}:{seconds % 60:02d}'

    v = to_seconds(video_len)
    p = to_seconds(pos)
    st = to_seconds(op_start)
    e = to_seconds(op_end)

    for command in commands:
        if st <= p <= e:	#오프닝 걸리면
            p = e	#오프닝 끝으로
        if command == "prev":
            p = max(p - 10, 0)	#p - 10초와 0초 중에 큰 수로
        elif command == "next":
            p = min(p + 10, v)	#p + 10초와 영상길이만큼 중에 작은 수로
        if st <= p <= e:	#위에 조건문 다 거쳐 왔는데 또 오프닝 걸릴 수 있으므로
            p = e

    return to_string(p)

훨씬 깔끔해졌다.

728x90