본문 바로가기
알고리즘 문제풀이

[프로그래머스] 주차 요금 계산 (Swift)

by SiO2whocode 2022. 3. 10.
728x90

https://programmers.co.kr/learn/courses/30/lessons/92341?language=swift 

 

코딩테스트 연습 - 주차 요금 계산

[180, 5000, 10, 600] ["05:34 5961 IN", "06:00 0000 IN", "06:34 0000 OUT", "07:59 5961 OUT", "07:59 0148 IN", "18:59 0000 IN", "19:09 0148 OUT", "22:59 5961 IN", "23:00 5961 OUT"] [14600, 34400, 5000]

programmers.co.kr

kakao 2022 blind recruitment

기본 시간, 기본 요금, 단위 시간, 단위 요금이 주어지고

차량의 입차, 출차 시간이 시간의 순서대로 담긴 배열이 주어진다.

차량의 주차요금을 차량번호의 오름차순으로 반환하는 문제

 

접근방법

스택을 사용하지 않아도 되지만 논리를 이해하기 쉽게 차량별 스택을 사용했다.

이 스택에는 차량의 입차시간이 담긴다. (이미 입차된 차가 또 입차하지 않으므로 사실상 스택에는 1개의 값 이상은 담기지 않는다)

출차 정보가 들어오면 스택에서 입차정보를 빼내 이용 시간을 구한다. 그리고 이용시간을 담은 딕셔너리에 값을 더한다.

이렇게 모든 record에 대해 입차, 출차 정보를 이용하여 이용시간을 구한 후에

 

입차정보만 있고 출차정보는 없는 차량에 대해 23:59시간을 출차시간으로 간주하여 이용시간을 구한 뒤 값을 더해준다.

 

이렇게 되면 차량별 이용시간이 구해졌다.

이용시간을 토대로 주차요금을 계산하는 공식은

이용시간이 기본시간보다 적거나 같을 경우 기본요금만 부과,

이용시간이 기본시간보다 많을 경우 기본요금 + 올림((이용시간 - 기본시간)/단위시간)*단위요금을 부과했다.

 

주차요금이 담긴 컬렉션 타입이 딕셔너리이므로 딕셔너리를 키값(자동차번호 String)을 기준으로 정렬한 뒤

얻어진 배열에서 value값만 추출해서 반환한다.

 

소스코드

import Foundation

let MAX_OUT_TIME:Int = 23*60 + 59

func solution(_ fees:[Int], _ records:[String]) -> [Int] {
    let minOfUse:[String:Int] = getMinutesOfUse(records)
    let expenses:[String:Int] = getExpenses(minOfUse, fees)
    let result:[Int] = expenses.sorted {$0.key < $1.key }.map{ $0.value }
    return result
}

func getMinutesOfUse(_ records:[String]) -> [String:Int] {
    var minOfUse:[String:Int] = [:]
    var stack:[String:[Int]] = [:]
    
    for record in records {
        let recordArr: [String] = record.components(separatedBy:" ")
        let time:Int = getMinutesOf(recordArr[0])
        let carNum:String = recordArr[1]
        if recordArr[2] == "IN" {
            stack[carNum] = [time]
        } else {
            let usingMin:Int = time - (stack[carNum]!.removeLast())
            if minOfUse[carNum] == nil {
                minOfUse[carNum] = usingMin
            } else {
                minOfUse[carNum]? += usingMin
            }
        }
    }
    
    for car in stack {
        if !car.value.isEmpty {
            let usingMin:Int = MAX_OUT_TIME - car.value[0]
            let carNum:String = car.key
            if minOfUse[carNum] == nil {
                minOfUse[carNum] = usingMin
            } else {
                minOfUse[carNum]? += usingMin
            }
        }
    }
    
    return minOfUse
}

func getMinutesOf(_ time:String) -> Int {
    let hourMin:[Int] = time.components(separatedBy:":").map{ Int($0) ?? 0 }
    return hourMin[0]*60 + hourMin[1]
}

func getExpenses(_ minOfUse:[String:Int], _ fees:[Int]) -> [String:Int] {
    return minOfUse.mapValues {
        if $0 <= fees[0] {
            return fees[1]
        } else {
            return fees[1] + Int(ceil(Double($0 - fees[0])/Double(fees[2])))*fees[3]
        }
    }
}
728x90