동영상 재생기 - [PCCP 기출문제]

이지영·2025년 1월 23일

[문제 설명]

당신은 동영상 재생기를 만들고 있습니다. 당신의 동영상 재생기는 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초 후로 이동하는 명령입니다.

[문제 링크]

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

[처음 풀이]

문제 풀 때 오프닝 구간 처리를 생각하지 못해서 틀렸었다.
작업 이후의 결과값 즉 prev버튼 또는 next버튼이 눌렸을 때 오프닝 구간에 들어갈 경우를
생각하지 못해서 틀렸었다.

작업 시작과 마지막에 해당 경우일 경우 오프닝 마지막 시간으로 이동하는 코드를 작성했더니 테스트 케이스가 잘 통과 되었다.

function solution(video_len, pos, op_start, op_end, commands) {
  	// 현재 시간을 ms로 변환
    const [mm,ss] = pos.split(':');
    let currentMs = Number(mm)* 60 + Number(ss);
    // 오프닝 시작 시간을 ms로 변환
    const [op_start_mm, op_start_ss] = op_start.split(':');
    const op_startTime = Number(op_start_mm)* 60 + Number(op_start_ss); 
    // 오프닝 종료 시간을 ms로 변환
    const [op_end_mm, op_end_ss] = op_end.split(':');
    const op_endTime = Number(op_end_mm)* 60 + Number(op_end_ss);
    // 비디오 길이를 ms로 변환
    const [video_len_mm, video_len_ss] = video_len.split(':');
    const videoTime = Number(video_len_mm)* 60 + Number(video_len_ss);
    
  // 사용자가 입력한 명령에 따른 next,prev처리
    commands.forEach((item)=>{
      // 오프닝 구간에 들어가면 오프닝 종료 구간으로 이동
        if(op_startTime <= currentMs && currentMs <= op_endTime){
            currentMs = op_endTime;
        }
        if(item === "next"){
            currentMs = Math.min(videoTime, currentMs + 10)
        } else {
            currentMs = Math.max(0,currentMs - 10)
        }
      // 입력한 명령을 실행한 뒤에도 (명령어가 1개일 경우 때문에 추가) 
      // 오프닝 구간에 들어가면 오프닝 종료 구간으로 이동
        if(op_startTime <= currentMs && currentMs <= op_endTime){
            currentMs = op_endTime;
        }
    })
  
  // 결과를 ms -> "mm:ss"형태로 변형  
    const [result_mm, result_ss] = [Math.floor(currentMs / 60),currentMs % 60]
    // 분 초가 10 미만일때를 위해 추가 (예 08:09)
    return `${result_mm < 10 ? '0' + result_mm : result_mm}:${result_ss < 10 ? '0' + result_ss : result_ss}`;
}

일단 테스트 케이스는 모두 성공

이젠 반복되는 작업을 함수로 분리해보겠다.

[수정한 풀이]

function solution(video_len, pos, op_start, op_end, commands) {
    // 시간 문자열을 ms로 변환
    const timeToMs = (time) => {
        const [mm,ss] = time.split(':').map(Number);
        return mm * 60 + ss
    }
    
    let currentMs = timeToMs(pos);
    const op_startTimeMs = timeToMs(op_start);
    const op_endTimeMS = timeToMs(op_end);
    const videoTimeMs = timeToMs(video_len);
    
    // ms를 문자열 시간으로 변환
    const resultTimeToMs = (ms) => {
        const mm = Math.floor(ms/60);
        const ss = ms % 60;
        const result = `${mm < 10 ? '0' + mm : mm }:${ss < 10 ? '0' + ss : ss}`
        return result
    }
    
    commands.forEach((item)=>{
        // 구간 체크 
        if(op_startTimeMs <= currentMs && currentMs <= op_endTimeMS){
            currentMs = op_endTimeMS;
        }
        if(item === "next"){
            currentMs = Math.min(videoTimeMs, currentMs + 10)
        } else {
            currentMs = Math.max(0,currentMs - 10)
        }
        // 작업 이후 결과값이 오프닝 구간일 경우를 위해 추가
        if(op_startTimeMs <= currentMs && currentMs <= op_endTimeMS){
            currentMs = op_endTimeMS;
        }
    })
    return resultTimeToMs(currentMs)
}

0개의 댓글