Kotlin/Algorithm Problems

<프로그래머스> 주차 요금 계산(Lv.2)

re트 2023. 11. 23. 12:13
728x90

[깃허브]

https://github.com/heesoo-park/ForCodeKata/tree/main/%EC%A3%BC%EC%B0%A8%20%EC%9A%94%EA%B8%88%20%EA%B3%84%EC%82%B0

[프로그래머스]

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

 

이렇게 문제 지문이 긴건 처음이었다... 

읽기만 하는데도 약간 움찔했다.

그래도 문제 자체가 원하는 값은 심플해서 차근차근 순서를 세워 문제 풀이를 시작했다.

 

가장 처음에는 문제를 잘못 이해한 상태로 코드를 완성했다.

이게 무슨 소리냐면 문제에서는 '입/출차 내역을 바탕으로 차량별 누적 주차시간을 계산하여 요금을 구하시오.'라고 했는데 나는 입/출차가 이루어졌을 때마다 차량별 주차시간을 계산하여 요금을 구했기 때문이다...ㅎ

코드를 다 완성하고 예시를 돌려봤을 때 다른 값이 나오고 예제를 다시 해체해보고 나서야 문제를 잘못 이해했음을 깨달았다.

이거 완성하는데도 시간 좀 걸렸는데... 그래도 큰 틀은 바꾸지 않아도 됐기에 금방까지는 아니고 적당히 시간을 써서 코드를 변경했다.

 

처음으로 MutableMap 타입 변수를 2개 만들었다.

하나는 차량번호와 입차시간을 저장하는 용도, 다른 하나는 차량번호와 주차시간을 저장하는 용도다.

사실 차량번호와 주차요금을 저장하는 용도로 하나 더 만들면 보기에, 이해하기에도 깔끔할텐데 배고파서인지 그냥 주차시간을 계산하면서 주차요금으로 자연스레 변경시켰더라

그래서 그냥 2개만 썼다.

 

그리고 나서는 records를 돌면서 필요한 부분들을 잘라 변수로 저장했다.(substring 사랑해요~)

그리고는 입차하는 차와 출차하는 자를 분류하여 진행했다.

이 때까지는 차량번호와 주차시간이 저장된다.

출차하는 차가 있으면 차량번호와 입차시간이 담긴 MutableMap에서 삭제했다.(새로 입차할 때 새로 입력하기 위해서)

 

위 반복문이 마치고나서는 입차만 하고 출차하지 않은 차들을 돌면서 강제 출차시켰다...!!

출차와 거의 동일한 코드였다.

하지만 여기서 오류가 발생했었는데 바로 remove 함수때문이었다!! 라고 하기에는 내가 인지하지 않고 그냥 넣은게 잘못이긴하지...

어쨌든 remove 함수로 인해서 반복문의 인덱스가 변하게 되고 forEach 문이 혼란스러워하며 튕기더라

그래서 이 부분을 없앴더니 잘 돌아갔다.

'앞의 반복문에서는 remove 함수 쓸 때 잘 돌아갔는데...?' 하면서 보니까 거기서는 remove하는 MutableMap과 상관없는 records를 돌고 있었기 때문에 그런 거였다.ㅎㅎ

 

주차요금 계산은 차량번호와 주차시간이 저장되어 있는 MutableMap을 돌면서 처리했고 사칙연산에다가 올림처리만 추가하면 됐기 때문에 금방 할 수 있었다.

 

마지막으로 차량번호가 작은 자동차 순으로 주차요금을 정렬해야했기 때문에 바로!! 전에 풀었던 귤 고르기 문제를 갔다.

여기서 MutableMap의 요소들을 가지고 정렬하는 걸 했었기 때문이다.(블로그에 올려놓기 잘 했어~)

 - 귤고르기 : https://retry-thinksubox.tistory.com/10

MutableMap을 List로 변환하고 sortedBy 함수를 통해 정렬하고 다시 Map으로 변환(이제 안 변하기 때문에 그냥 Map으로 변환했다.)

주차요금을 answer에 넣는 것으로 마무리!!

 

해당 방법으로 작성한 코드는 다음과 같다.

class Solution {
    fun solution(fees: IntArray, records: Array<String>): IntArray {
        var answer: IntArray = intArrayOf()
        // 차량번호, 입차시간
        val check: MutableMap<String, String> = mutableMapOf()
        // 차량번호, 주차시간 -> 차량번호, 주차요금
        val calculate: MutableMap<String, Int> = mutableMapOf()

        for (idx in records.indices) {
            // 현재 시간
            val time = records[idx].substring(0..4)
            // 차량번호
            val carNum = records[idx].substring(6..9)
            // IN or OUT
            val flag = records[idx].substring(11)

            // 입차
            if (flag == "IN" && !check.containsKey(carNum)) {
                check[carNum] = time
                if (!calculate.containsKey(carNum)) calculate[carNum] = 0
            }

            // 출차
            if (flag == "OUT" && check.containsKey(carNum)) {
                val inTime = check[carNum]!!.substring(0..1).toInt() * 60 + check[carNum]!!.substring(3..4).toInt()
                val outTime = time.substring(0..1).toInt() * 60 + time.substring(3..4).toInt()
                val totalTime = outTime - inTime

                calculate[carNum] = calculate[carNum]!!.plus(totalTime)
                check.remove(carNum)
            }
        }
        // 출차 안 한 차들 강제 출차
        check.forEach {
            val inTime = it.value.substring(0..1).toInt() * 60 + it.value.substring(3..4).toInt()
            val outTime = 1439
            val totalTime = outTime - inTime

            calculate[it.key] = calculate[it.key]!!.plus(totalTime)
        }

        // 주차 계산
        calculate.forEach {
            val totalTime = it.value
            calculate[it.key] = 0

            if (totalTime <= fees[0]) {
                calculate[it.key] = calculate[it.key]!!.plus(fees[1])
            } else {
                val overTime = totalTime - fees[0]
                // 단위시간 올림 처리
                val overUnitTime = if (overTime % fees[2] != 0) overTime / fees[2] + 1 else overTime / fees[2]

                calculate[it.key] = calculate[it.key]!!.plus(fees[1] + overUnitTime * fees[3])
            }
        }
        
        // 차량번호에 오름차순으로 정렬
        val sortedByCarName = calculate.toList().sortedBy { it.first }.toMap()
        for (record in sortedByCarName) {
            answer += record.value
        }

        return answer
    }
}

(순서대로 차근차근 하니까 풀리더라... 푸는 시간은 좀 줄여야겠지만)

반응형