본문 바로가기
Thinking/Programmers

[PCCP 기출문제] 1번 / 동영상 재생기 C++

by Dev_카페인 2024. 11. 7.
반응형

[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가지 기능을 구현해야 합니다:

  1. 10초 전으로 이동(prev): 재생 위치를 10초 이전으로 이동.
  2. 10초 후로 이동(next): 재생 위치를 10초 후로 이동.
  3. 오프닝 건너뛰기: 재생 위치가 오프닝 구간에 있으면 오프닝 끝 지점으로 이동.

이때, 시간을 "mm" 형식에서 초 단위로 변환하여 계산한 후 다시 "mm" 형식으로 변환하는 것이 유리합니다.

문제 풀이 접근

  1. 문자열 시간을 초로 변환:
    • "mm" 형식의 시간을 초로 변환해 계산을 쉽게 만듭니다. 예를 들어, 13:00은 780초가 됩니다.
  2. 각 명령어 수행:
    • 각 명령어에 따라 재생 위치를 조정하고, 재생 위치가 오프닝 구간에 속해 있는지 확인해 필요 시 오프닝 끝 지점으로 이동합니다.
  3. 초를 다시 "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);
}

 

코드 설명

  1. timeToSeconds 함수:
    • "mm:ss" 형식의 문자열을 받아 총 초로 변환합니다.
    • stoi 함수를 사용해 문자열의 분과 초를 정수로 변환한 후, 총 초로 계산합니다. 분 * 60 + 초 형식으로 계산하여 반환합니다.
  2. secondsToTime 함수:
    • 총 초를 받아서 다시 "mm:ss" 형식의 문자열로 변환합니다.
    • stringstream을 사용하여, setfill('0')과 setw(2)를 통해 두 자리 숫자 형식(00)으로 맞춥니다. 예를 들어, 5초는 05로 출력됩니다.
  3. solution 함수:
    • 동영상 길이, 현재 위치, 오프닝 구간 시작 및 끝을 초 단위로 변환하여 저장합니다.
    • 명령어 리스트 commands를 반복하면서 각 명령을 처리합니다.
      • prev 명령어: 현재 위치에서 10초 전으로 이동합니다. 만약 현재 위치가 10초보다 작다면 영상 처음(0초)으로 이동합니다.
      • next 명령어: 현재 위치에서 10초 후로 이동합니다. 영상 길이(videoLength)를 초과하지 않도록 합니다.
    • 각 명령어 처리 후, 현재 위치가 오프닝 구간에 포함된다면 오프닝 끝 지점으로 이동합니다.
  4. 결과 반환:
    • 모든 명령어 처리가 완료되면 최종 위치를 "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)

 

코드 설명

  1. 시간 변환 함수:
    • time_to_seconds: "mm" 형식을 초 단위로 변환하는 함수입니다.
    • seconds_to_time: 초 단위를 "mm" 형식으로 변환하는 함수입니다.
  2. 명령어 처리 루프:
    • commands 리스트의 각 명령어를 순회하며 prev, next 명령어를 처리합니다.
    • prev 명령어는 현재 위치에서 10초 전으로 이동시키고, 만약 0초 미만으로 갈 경우 0초로 고정합니다.
    • next 명령어는 현재 위치에서 10초 후로 이동시키고, 영상 끝을 넘어가지 않도록 합니다.
    • 오프닝 구간에 있는 경우 오프닝 끝 위치로 자동 이동합니다.
  3. 결과 반환:
    • 모든 명령어 처리가 끝난 후 최종 재생 위치를 "mm" 형식으로 변환하여 반환합니다.

시간 복잡도

이 코드의 시간 복잡도는 O(N)입니다. N은 commands 리스트의 길이로, 각 명령어를 한 번씩 순회하기 때문입니다. 명령어 수가 많더라도 성능에 큰 영향을 미치지 않습니다.

 

반응형