카테고리 없음

[프로그래머스] level2 주차 요금 계산 - 구현

nagrang 2025. 2. 26. 17:05

1. 문제

문제 설명

문제 설명

주차장의 요금표와 차량이 들어오고(입차) 나간(출차) 기록이 주어졌을 때, 차량별로 주차 요금을 계산하려고 합니다. 아래는 하나의 예시를 나타냅니다.

  • 요금표

 

  • 입/출차 기록

시각(시:분)차량 번호내역

  • 자동차별 주차 요금

차량 번호누적 주차 시간(분)주차 요금(원)

  • 어떤 차량이 입차된 후에 출차된 내역이 없다면, 23:59에 출차된 것으로 간주합니다.
    • 0000번 차량은 18:59에 입차된 이후, 출차된 내역이 없습니다. 따라서, 23:59에 출차된 것으로 간주합니다.
  • 00:00부터 23:59까지의 입/출차 내역을 바탕으로 차량별 누적 주차 시간을 계산하여 요금을 일괄로 정산합니다.
  • 누적 주차 시간이 기본 시간이하라면, 기본 요금을 청구합니다.
  • 누적 주차 시간이 기본 시간을 초과하면, 기본 요금에 더해서, 초과한 시간에 대해서 단위 시간 마다 단위 요금을 청구합니다.
    • 초과한 시간이 단위 시간으로 나누어 떨어지지 않으면, 올림합니다.
    • ⌈a⌉ : a보다 작지 않은 최소의 정수를 의미합니다. 즉, 올림을 의미합니다.

주차 요금을 나타내는 정수 배열 fees, 자동차의 입/출차 내역을 나타내는 문자열 배열 records가 매개변수로 주어집니다. 차량 번호가 작은 자동차부터 청구할 주차 요금을 차례대로 정수 배열에 담아서 return 하도록 solution 함수를 완성해주세요.

 

 

2. 구현

입출차만 관리하면서 비용을 계산하면 될 것이라고 생각하고 구현

 

입차

`hastMap`이용해서 <차 번호 : 입차시간> 을 저장하기로 함.

이때 시간 계산의 편의를 위해 입차시간은 분 단위로 int형태로 계산하기로 함

# "01:30" -> 1*60 + 30 => 90

 

출차

1. 주차 요금 구하기 : `hastMap`에 저장된 입차시간과 출차시간을 가지고 총 비용을 구함

2. 결과 저장 : 바로 `outCars` 리스트에 저장. 

3. `hashMap`에서 삭제 : 그리고 출차된 차량임을 알기위해 `hashMap`에서 삭제. 

 

하지만 풀다가 놓친 점

1. 같은 차가 하루에 2번 이상올 수 있음

2. 나갈 때마다 계산하는 것이 아니라 하루 누적금액을 계산하는 거였음

3. 또한 출력결과가 차 번호 순대로 비용을 출력해야 하니, 결과를 저장하는 `outCars` 는 트리맵으로 구성

 

다시 구현

입차

바뀌지 않음

 

출차

1. 결과 저장 List -> TreeMap으로 : ,이때 비용을 계산하고 결과 리스트에 저장하는 것이 아니라, 누적된 주차 시간을 별도의 `outCars` 트리맵에 <차 번호 : 누적된 주차 시간>을 저장하기로 함. 마찬가지로 출차된 차량임을 알기위해 `hashMap`에서 삭제. 

 

 

3. 어려웠던 점

1. 결과 소수점에서 올림하기

-> `Math.ceil` 함수를 이용하면 올림할 수 있음 

# 1.1 -> 2

 

2. 정수의 연산에 Math.ceil 해봤자 이미 소수점이 날아갔음

계속 올림이 안되길래 뭐가 문제지 보다가, int 형/ int 형 때문에 이미 소수점 내림이 되고 있었음

 

3. stream

리스트를 배열로 전환할 때 코드가 너무 더러워서 stream 찾아봄 

int [] costs = new int[outCars.size()];
        int idx = 0;
        for(String c : outCars.keySet()){
            int t = outCars.get(c);
            int operTime = outCars.get(c);
            if(operTime <= baseTime){
                costs[idx++] = baseCost;
            }
            else{
                costs[idx++] = baseCost + (int)(Math.ceil((operTime - baseTime)*1.0 / perTime)) * perCost;
            }

 

return outCars.values()
            .stream()
            .mapToInt(time -> calculateFee(time, baseTime, baseCost, perTime, perCost)).toArray();

 

 

4. 전체 코드

import java.util.*;


class Solution {
    
    public int[] solution(int[] fees, String[] records) {
        int[] answer = {};
        
        // 1. 변수 선언
        int baseTime = fees[0];
        int baseCost = fees[1];
        int perTime = fees[2];
        int perCost = fees[3];
        
        HashMap<String, Integer> inCars = new HashMap<String, Integer>();
        TreeMap<String, Integer> outCars = new TreeMap<String, Integer>();
        
        // 2. 레코드 마다 관리
        for(String record : records){
            String [] op = record.split(" ");
            
            int time = timeToInt(op[0]);
            String carNum = op[1];
            
            if(op[2].equals("IN")){
                // 입차 - 해쉬셋에 (차 번호 : 입차시간) 저장, 입차시간은 분단위
                inCars.put(carNum, time);
            }
            else if(op[2].equals("OUT")){
                // 출차 - 입차 시간 계산, 차 삭제, 레코드 저장
                int inTime = inCars.get(carNum);
                
                outCars.put(carNum, outCars.getOrDefault(carNum, 0) + (time - inCars.remove(carNum)));
            }
        }
        
        // 출차되지 않은 차 출차
        int endOfDay = 60*23 + 59;
        for(String car : inCars.keySet()){
            int inTime = inCars.get(car);
            outCars.put(car, outCars.getOrDefault(car, 0) + (endOfDay - inTime));
        }
        
        return outCars.values()
            .stream()
            .mapToInt(time -> calculateFee(time, baseTime, baseCost, perTime, perCost)).toArray();
        
    }
 
    private int calculateFee(int time, int baseTime, int baseCost, int perTime, int perCost) {
        if (time <= baseTime) return baseCost;
        return baseCost + (int) Math.ceil((time - baseTime) / (double) perTime) * perCost;
    }
    
    public static int timeToInt(String time){
        String [] st = time.split(":");
        int h = Integer.parseInt(st[0]);
        int m = Integer.parseInt(st[1]);
        
        return h*60 + m;
    }
}