안녕하세요. 회사와 함께 성장하고 싶은 KOSE입니다.

 

이번 포스팅은 프로그래머스 주차 요금 계산에 대한 글을 작성하고자 합니다.

 

문제 출처: https://school.programmers.co.kr/learn/courses/30/lessons/92341

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

1. 풀이 소스

import java.util.*;
import static java.lang.Integer.parseInt;

class Solution {
    public int[] solution(int[] fees, String[] records) {
        Parking park = new Parking(fees); // 인스턴스 생성
        return park.apply(records);
    }   
}

class Parking {
    static int basicTime; // 기본 제공 시간
    static int basicFee; // 기본 요금
    static int unit; // 단위 시간
    static int unitFee; // 단위 요금
    static final int LAST_TIME = 1439; // 1380 + 59 = 1439 (23:59)
    
    Map<String, ParkFee> map = new HashMap<>(); // 차량 번호 기록 map
    
    class ParkFee {
        int inTime; // 입차
        int usedTime; // 누적 사용 시간

        ParkFee(int inTime) {
            this.inTime = inTime;
        }
    }
    
    Parking(int[] fees) { // 초기화
        basicTime = fees[0];
        basicFee = fees[1];
        unit = fees[2];
        unitFee = fees[3];
    }
    
    void add(String carNumber, int inTime) { // time: 분으로 설정된 시간
        if (map.containsKey(carNumber)) { 
            ParkFee parkFee = map.get(carNumber); // 차량 시간이 있다면 intime 값 변경
            parkFee.inTime = inTime;
        } else map.put(carNumber, new ParkFee(inTime)); // 없다면 인스턴스 생성
    }
    
    int out(String carNumber, int outTime) {     
        ParkFee parkFee = map.get(carNumber);
        int inTime = parkFee.inTime;
        parkFee.inTime = -1;  // 00:00의 경우 inTime이 0이므로 -1로 설정
        return outTime - inTime; // 출차 - 입차 시간 계산
    }
    
    int calFee(int usedTime) {
        if (usedTime <= basicTime) return basicFee; // 만약 기본 제공 시간보다 적은 경우 기본 요금
        int additionalTime = (usedTime - basicTime) % unit == 0 ?  (usedTime - basicTime) / unit : ((usedTime - basicTime) / unit) + 1;   // 단위 계산을 위한 올림 계산
        return basicFee + additionalTime * unitFee; // 기본 요금 + 추가 시간 * 단위 비용
    }
    
    
    int[] apply (String[] records) {
        for (String record : records) {
            String[] rc = record.split(" ");
            String[] timeZone = rc[0].split(":");
            int time = parseInt(timeZone[0]) * 60 + parseInt(timeZone[1]);
            
            String carNumber = rc[1];
            boolean in = rc[2].equals("IN");
            
            if (in) add(carNumber, time);
            
            else {
                ParkFee parkFee = map.get(carNumber);
                parkFee.usedTime += out(carNumber, time); // 출차 - 입차로 누적 시간 업데이트
            }          
        }
        
        List<String> keys = new ArrayList<>();
        keys.addAll(map.keySet()); // ketSet (차 번호) 모두 keys에 업데이트
        keys.sort(Comparator.comparing(s -> s)); // 차 번호로 정렬
        
        int[] result = new int[keys.size()];
        
        for (int i = 0; i < keys.size(); i++) {
            ParkFee parkFee = map.get(keys.get(i));
           
            int fee = 0;
            if (parkFee.inTime != -1) {
                parkFee.usedTime += LAST_TIME - parkFee.inTime; // 누적 시간 업데이트
            } 
            
            result[i] = calFee(parkFee.usedTime); // 누적시간으로 금액 계산
        }
        
        return result;
    }
}

 

 

2. 풀이 과정

 

해당 문제는 inTime, outTime을 설정할 때, 누적 시간을 체크해야 하는 부분이 있습니다.

즉, 여러 번 입차 및 출차하였더라도 누적 시간으로 금액을 측정해야하므로 ParkFee라는 객체에 누적 시간을 더하는 usedTime을 적용하여, 출차 시 출차 - 입차 시간을 더하는 과정을 수행하였습니다.

 

처음에 실수한 부분은 "00:00"은 시간 * 60 + 분 설정에 의하면 0이 나옵니다. 여기서 출차 후 inTime을 0으로 설정하게 되면,
해당 값이 00:00에 입차를 하여 출차가 된 것인지 아니면 아직 출차가 안된 채로 남아있는지 구분이 어려울 수 있습니다.
따라서, -1로 설정하여 구분하도록 하였고 마지막에 calFee로 요금을 계산하는 과정을 처리하였습니다.

 

자세한 사항은 주석으로 표기하였습니다.

 

감사합니다.!

+ Recent posts