[PCCP 기출문제] 1번 / 동영상 재생기 C++
문제 설명
당신은 동영상 재생기를 만들고 있습니다. 당신의 동영상 재생기는 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 하면 됩니다.
코드 풀이
이 문제는 동영상의 재생 위치를 조작하는 기능을 구현해야 하는 문제로, 주어진 조건에 맞게 시간 계산과 조건 분기를 잘 활용해야 합니다.
문제 분석
문제에서는 동영상 재생기의 3가지 기능을 구현해야 합니다:
- 10초 전으로 이동(prev): 재생 위치를 10초 이전으로 이동.
- 10초 후로 이동(next): 재생 위치를 10초 후로 이동.
- 오프닝 건너뛰기: 재생 위치가 오프닝 구간에 있으면 오프닝 끝 지점으로 이동.
이때, 시간을 "mm" 형식에서 초 단위로 변환하여 계산한 후 다시 "mm" 형식으로 변환하는 것이 유리합니다.
문제 풀이 접근
- 문자열 시간을 초로 변환:
- "mm" 형식의 시간을 초로 변환해 계산을 쉽게 만듭니다. 예를 들어, 13:00은 780초가 됩니다.
- 각 명령어 수행:
- 각 명령어에 따라 재생 위치를 조정하고, 재생 위치가 오프닝 구간에 속해 있는지 확인해 필요 시 오프닝 끝 지점으로 이동합니다.
- 초를 다시 "mm" 형식으로 변환:
- 모든 명령어를 처리한 후 최종 결과를 "mm" 형식으로 변환하여 반환합니다.
전체 코드
#include <string>
#include <vector>
#include <sstream>
#include <iomanip>
using namespace std;
// "mm:ss" 형식을 초 단위로 변환하는 함수
int timeToSeconds(const string& time) {
int minutes = stoi(time.substr(0, 2));
int seconds = stoi(time.substr(3, 2));
return minutes * 60 + seconds;
}
// 초 단위를 "mm:ss" 형식의 문자열로 변환하는 함수
string secondsToTime(int seconds) {
int minutes = seconds / 60;
seconds = seconds % 60;
stringstream ss;
ss << setfill('0') << setw(2) << minutes << ":" << setfill('0') << setw(2) << seconds;
return ss.str();
}
string solution(string video_len, string pos, string op_start, string op_end, vector<string> commands) {
int videoLength = timeToSeconds(video_len);
int currentPos = timeToSeconds(pos);
int openingStart = timeToSeconds(op_start);
int openingEnd = timeToSeconds(op_end);
for (const string& command : commands) {
if (command == "prev") {
currentPos = max(0, currentPos - 10); // 10초 이전으로 이동 (영상 처음보다 작아지면 0으로 설정)
} else if (command == "next") {
currentPos = min(videoLength, currentPos + 10); // 10초 이후로 이동 (영상 끝을 초과하면 영상 길이로 설정)
}
// 현재 위치가 오프닝 구간에 속할 경우 오프닝 끝 지점으로 이동
if (openingStart <= currentPos && currentPos <= openingEnd) {
currentPos = openingEnd;
}
}
return secondsToTime(currentPos);
}
코드 설명
- timeToSeconds 함수:
- "mm:ss" 형식의 문자열을 받아 총 초로 변환합니다.
- stoi 함수를 사용해 문자열의 분과 초를 정수로 변환한 후, 총 초로 계산합니다. 분 * 60 + 초 형식으로 계산하여 반환합니다.
- secondsToTime 함수:
- 총 초를 받아서 다시 "mm:ss" 형식의 문자열로 변환합니다.
- stringstream을 사용하여, setfill('0')과 setw(2)를 통해 두 자리 숫자 형식(00)으로 맞춥니다. 예를 들어, 5초는 05로 출력됩니다.
- solution 함수:
- 동영상 길이, 현재 위치, 오프닝 구간 시작 및 끝을 초 단위로 변환하여 저장합니다.
- 명령어 리스트 commands를 반복하면서 각 명령을 처리합니다.
- prev 명령어: 현재 위치에서 10초 전으로 이동합니다. 만약 현재 위치가 10초보다 작다면 영상 처음(0초)으로 이동합니다.
- next 명령어: 현재 위치에서 10초 후로 이동합니다. 영상 길이(videoLength)를 초과하지 않도록 합니다.
- 각 명령어 처리 후, 현재 위치가 오프닝 구간에 포함된다면 오프닝 끝 지점으로 이동합니다.
- 결과 반환:
- 모든 명령어 처리가 완료되면 최종 위치를 "mm:ss" 형식의 문자열로 변환하여 반환합니다.
Python 코드
def time_to_seconds(time):
minutes, seconds = map(int, time.split(":"))
return minutes * 60 + seconds
def seconds_to_time(seconds):
minutes = seconds // 60
seconds = seconds % 60
return f"{minutes:02}:{seconds:02}"
def solution(video_len, pos, op_start, op_end, commands):
video_length = time_to_seconds(video_len)
current_pos = time_to_seconds(pos)
opening_start = time_to_seconds(op_start)
opening_end = time_to_seconds(op_end)
for command in commands:
if command == "prev":
current_pos = max(0, current_pos - 10)
elif command == "next":
current_pos = min(video_length, current_pos + 10)
# 오프닝 구간에 있을 경우 오프닝 끝으로 이동
if opening_start <= current_pos <= opening_end:
current_pos = opening_end
return seconds_to_time(current_pos)
코드 설명
- 시간 변환 함수:
- time_to_seconds: "mm" 형식을 초 단위로 변환하는 함수입니다.
- seconds_to_time: 초 단위를 "mm" 형식으로 변환하는 함수입니다.
- 명령어 처리 루프:
- commands 리스트의 각 명령어를 순회하며 prev, next 명령어를 처리합니다.
- prev 명령어는 현재 위치에서 10초 전으로 이동시키고, 만약 0초 미만으로 갈 경우 0초로 고정합니다.
- next 명령어는 현재 위치에서 10초 후로 이동시키고, 영상 끝을 넘어가지 않도록 합니다.
- 오프닝 구간에 있는 경우 오프닝 끝 위치로 자동 이동합니다.
- 결과 반환:
- 모든 명령어 처리가 끝난 후 최종 재생 위치를 "mm" 형식으로 변환하여 반환합니다.
시간 복잡도
이 코드의 시간 복잡도는 O(N)입니다. N은 commands 리스트의 길이로, 각 명령어를 한 번씩 순회하기 때문입니다. 명령어 수가 많더라도 성능에 큰 영향을 미치지 않습니다.
'Thinking > Programmers' 카테고리의 다른 글
LV2 PCCP 기출문제 2번 석유 시추 (1) | 2024.02.21 |
---|---|
2024 KAKAO WINTER INTERNSHIP 가장 많이 받은 선물 (0) | 2024.02.20 |
LV1 PCCP 기출문제 1번 붕대 감기 - 250137 (0) | 2024.02.20 |
프로그래머스 PCCE 기출문제 후기 (0) | 2024.02.19 |
C++ 프로그래머스 Lv5 집합과 쿼리 (0) | 2023.09.22 |