[프로그래머스] 2021 KAKAO BLIND RECRUITMENT - 광고 삽입

2 minute read

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

import Foundation

func solution(_ play_time:String, _ adv_time:String, _ logs:[String]) -> String {
    // 시청자들이 가장 많이 보는 구간에 공익광고 넣기.
    // play_time : 죠르디의 동영상 재생시간
    // adv_time : 광고 시간길이
    let playTime: Int = changeToSecond(play_time)
    let advTime: Int = changeToSecond(adv_time)
    
    // 파라미터 logs 원소는 H1:M1:S1-H2:M2:S2.
    let logs: [[Int]] = logs.map { $0.components(separatedBy: "-").map { changeToSecond($0)} }
    var timeline: [Int] = Array(repeating: 0, count: playTime + 1)
    
    if playTime == advTime {
        return "00:00:00"
    }
    
    for index in 0..<logs.count {
        // 시작하는 시간에는 시청구간이 추가되고,
        // 끝나는 시간에는 시청구간이 삭제.
        timeline[logs[index][0]] += 1
        timeline[logs[index][1]] -= 1
        
        // timeline 은 매초마다 시청이 시작된 횟수를 알 수 있음.(아직 시청중인 횟수는 알지 못함)
    }
    
    // 시청 중인 횟수도 추가해보자.
    // ✅ 아이디어 : 바로 전 timline 을 더해주면 알아서 이전에 끝나는 시간에 마이너스 된 값들이 계산된다.
    for index in 1..<timeline.count {
        timeline[index] += timeline[index - 1]
    }
    // 결국, timeline 은 매초마다 시청자 숫자만큼의 값을 갖게 됨.
    // 이중 광고 시간길이 동안 가장 많은 값을 가지는 가장 빠른 구간을 찾으면 됨.
    
    // ✅ 아이디어 : 이전값을 누적시켜서 어느 구간이 가장 시청자가 많은지 확인할 수 있다.
    // 위의 반복문 그대로 반복.
    // timeline : 00:00:00 부터 index + 1 까지 index + 1 초 간의 구간에 대한 누적 시청자
    for index in 1..<timeline.count {
        timeline[index] += timeline[index - 1]
    }
    
    // advTime 만큼의 구간에 대한 누적 시청자 수
    // -> timeline[index] - timeline[index - advTime]
    var max: Int = 0
    /// 가장 많은 누적 재생 시작 시간(초 단위)
    var maxTime: Int = 0
    
    for index in (advTime - 1)..<playTime {
        if index >= advTime {
            if timeline[index] - timeline[index - advTime] > max {
                max = timeline[index] - timeline[index - advTime]
                maxTime = index
            }
        } else {
            // advTime - 1. 즉, 0 부터 advTime 간의 구간에 대한 누적 시청자.
            max = timeline[index]
            maxTime = index
        }
    }
    
    // 시작 시간을 구해서 반환. HH:MM:SS
    // 누적된 시청자가 가장 많은 시간 - 광고시간
    return changeToTime(maxTime - advTime + 1)
}

/// 초 단위로 시간을 변환.
func changeToSecond(_ time: String) -> Int {
    let times: [Int] = time.components(separatedBy: ":").map { Int($0)! }
    
    return times[0] * 3600 + times[1] * 60 + times[2]
}

/// 초 단위를 시간으로 변환.
func changeToTime(_ seconds: Int) -> String {
    return "\(addZero(to: seconds / 3600)):\(addZero(to: seconds % 3600 / 60)):\(addZero(to: seconds % 60))"
}

/// 한 자릿수 시간에 0 추가
func addZero(to number: Int) -> String {
    return number < 10 ? "0\(number)" : "\(number)"
}

print(solution("02:03:55", "00:14:15", ["01:20:15-01:45:14", "00:40:31-01:00:00", "00:25:50-00:48:29", "01:30:59-01:53:29", "01:37:44-02:02:30"]))
// "01:30:59"

print(solution("99:59:59", "25:00:00", ["69:59:59-89:59:59", "01:00:00-21:00:00", "79:59:59-99:59:59", "11:00:00-31:00:00"]))
// "01:00:00"

print(solution("50:00:00", "50:00:00", ["15:36:51-38:21:49", "10:14:18-15:36:51", "38:21:49-42:51:45"]))
// "00:00:00"

Categories:

Updated: