My Boundary As Much As I Experienced

(2022 KAKAO BLIND RECRUITMENT) 주차 요금 계산 본문

Algorithm/Coding Test

(2022 KAKAO BLIND RECRUITMENT) 주차 요금 계산

Bumang 2023. 7. 19. 00:46

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

 

 

문제 수준:

레벨2

 

 

 

문제 요약:

자동차 요금 계산을 하는 문제.

1. 기본 시간 이내에 나갈 시 기본 요금만 부과.

2. 기본 시간을 초과할 시 n분 당 m원 부과.

3. 나갈 때 계산하는게 아니라 하루의 끝에 총 시간을 정산하는 방식

4. 하루가 지나도록 안 나가면(00:00분이 지나면), 23:59에 출차한 것으로 정산. 

 

 

 

입출력 예 (입력 / 출력):

fee[0]은 기본 시간, fee[1]은 기본 요금, fee[2]는 단위 시간, fee[3]은 단위 요금

records는 "시간 차번호 입차/출차" 꼴로 되어 있다.

 

번호판 숫자가 작은 것부터 요금을 배열로 정리해서 내야한다.

 

 

 

문제 풀이 전략:

들어온 시간 객체(inSpan)나간 시간 객체(outSpan)를 생성하여 활용한다.

 

그리고 차 번호를 고유값 key로 사용하여 (나간 시간 - 들어온 시간)을 하여

 

총 시간 기록용 객체(totalMinSum)에 기록한다.

 

마지막에 총 시간 기록용 객체에 있는 데이터를 기반으로 차 별 총 시간을 규칙에 맞추어 요금 정산한다.

 

 

 

 

내 풀이:

function solution(fees, records) {
    const [stdMinTime, stdFee, perMinTime, perFee] = fees
    const inSpan = {} // 입차 시간 객체
    const outSpan = {} // 출차 시간 객체
    const totalMinSum = {} // 총 시간 기록 객체
    const totalFee = {} // 총 요금 정리

    const result = [] // 채점 반환용 배열

    for (spec of records) { /* (입출차 시간 파악해서) 차 별로 머문 시간 계산하는 파트 */
        const recList = spec.split(" ") // 공백으로 나눠서
        const [recHourTime, recCarID, recWard] = recList // 시 단위 시간, 차번호, 방향을 변수로 얻음
        const recMinTime = convertMinute(recHourTime) // 시 단위 시간을 분 단위 시간으로 변환

        if (recWard === "IN") { // 만약 "입차"라면...
            inSpan[recCarID] = recMinTime // 입차 시간 객체에 기록
        } else { // 출차라면
            outSpan[recCarID] = recMinTime // 출차 시간 객체에 기록
            calculateTimeSpan(recCarID) // 몇 분 동안 주차했는지 계산하는 함수 호출 (출차 시간 - 입차 시간).
            // 몇 분 동안 주차했는지 계산하여 총 시간 객체(totalMinSum)에 기록한다.

            inSpan[recCarID] = null // 입차 기록 초기화
            outSpan[recCarID] = null // 출차 기록 초기화
        }
    }

    for (recCarID in inSpan) { /* 나가지 않은 차들 정산하는 파트*/ 
        if (inSpan[recCarID] !== null) { // 초기화 되지 않은 입차기록이 있다면
            outSpan[recCarID] = convertMinute("23:59") // 나가지 않고 하루 지난 것이므로 23:59로 정산...
            calculateTimeSpan(recCarID) // 다시 요금 구하기

            inSpan[recCarID] = null // 비로소 입차 시간 초기화
            outSpan[recCarID] = null // 비로소 출차 시간 초기화
        }
    }

    for (recCarID in inSpan) { // 요금 정산하는 파트
        if (totalMinSum[recCarID] <= stdMinTime) { // 기준 시간보다 총 시간이 짧거나 같다면
            totalFee[recCarID] = stdFee // 기본 요금만 내쇼!
        } else { // 기준 시간을 초과한다면
            totalFee[recCarID] = stdFee + perFee
                * Math.ceil((totalMinSum[recCarID] - stdMinTime) / perMinTime)
            // 기본 요금 + 단위 요금 * ((총 시간 - 기본 시간) / 단위 시간)의 반올림 만 내쇼!
        }
    }

    const IDOrder = Object.keys(totalFee).sort((a,b)=> a - b) //번호 작은 순서로 차 번호 정렬 
    for (let i = 0; i < IDOrder.length; i++) {
        result.push(totalFee[IDOrder[i]]) //번호 작은 순서대로 요금 정산했던거 result에 넣기
    }

    return result // 답 제출!!


    function calculateTimeSpan(recCarID) { /* 몇 분 있었는지 정산하는 함수 */
        const subMinTime = outSpan[recCarID] - inSpan[recCarID]
        totalMinSum[recCarID] = (totalMinSum[recCarID] || 0) + subMinTime
    }

    function convertMinute(time) { /* 분 단위로 변환하는 함수 */
        const temp = time.split(":")
        let [hour, min] = temp
        return Number(hour) * 60 + Number(min)
    }
}