개발저장소

[프로그래머스 Level 2] 주차 요금 계산 본문

Coding Test/Programmers

[프로그래머스 Level 2] 주차 요금 계산

개발소 2023. 11. 17. 14:03

문제

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

 

프로그래머스

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

programmers.co.kr

 

 

풀이

  • 주차장에 출입하는 차량 기록이 주어졌을 때, 주차 요금을 구하는 문제이다.
  • 입출차 기록은 시각, 차량 번호, 입출 내역으로 이루어져 있으며 모두 문자열로 주어진다.
  • 입차 후 출차 기록이 없다면 23시 59분에 출차한 것으로 계산한다.
  • 요금표는 기본 시간과 요금, 추가 단위 시간과 요금으로 이루어져 있으며 int형 배열로 주어진다.
  • 차량 번호가 작은 자동차부터 순서대로 주차 요금을 출력한다.
  • 한 차량이 출차 후 다시 입차할 수 있다는 점도 생각해야 한다.

 

문자열로 입력되는 정보를 다루고 구현하는 문제이다. 출입차 내역과 요금 계산 모두 HashMap을 사용하였다. 차량 번호를 key로 사용하여 시각 value를 검색하는 map, 그리고 마찬가지로 차량 번호를 key로 누적 시간을 계산하는 feeMap을 선언하였다. feeMap은 미리 모든 차량을 등록하고 시간을 0으로 초기화한다.

// 출입차를 파악하기 위한 map
HashMap<String, String> map = new HashMap<>();

// 요금을 계산하기 위한 map
HashMap<String, Integer> feeMap = new HashMap<>();

// 모든 차량의 요금을 계산하기 위한 초기값
for(int i = 0; i < records.length; i++){
    feeMap.put(records[i].split(" ")[1], 0);
}

 

입력되는 문자열은 split()을 사용해 문자열 배열로 만들어 준다. 이때 map에 차량이 존재하는 경우, 즉 입차 기록이 있는 경우 remove()를 사용하여 기록을 삭제함과 동시에 데이터를 입차 시간으로 저장한다. 동시에 문자열 배열로 받은 시간은 출차 시간으로 사용하여 차이를 이용해 전체 주차 시간을 계산한다. 

for(int i = 0; i < records.length; i++){
    String[] infos = records[i].split(" "); // 0 시간, 1 차 번호, 2 출입여부

    // 이미 입차한 차량이 존재해 출차를 하는 경우
    if (map.containsKey(infos[1])){
        // map에서 입차한 경우를 제거하며 입차 시간을 가져온다.
        String[] inTime = map.remove(infos[1]).split(":");
        String[] outTime = infos[0].split(":");

        int hour = Integer.parseInt(outTime[0]) - Integer.parseInt(inTime[0]);
        int minute = Integer.parseInt(outTime[1]) - Integer.parseInt(inTime[1]);

        // 요금 map에 누적 시간을 replace
        feeMap.replace(infos[1], feeMap.get(infos[1]) + 60 * hour + minute);

    } 

    // 입차하는 경우
    else {
        map.put(infos[1], infos[0]); // 차 번호, 시간
    }
}

 

모든 입출차 기록을 확인한 후 아직 출차하지 않은 차량을 판별한다. 이때, 출차는 23:59분에 한 것으로 시간을 계산한다.

// 아직 출차하지 않은 나머지 (23시 59분에 출차한 것으로 계산)
for(String key : map.keySet()){
    String[] inTime = map.get(key).split(":");

    int hour = 23 - Integer.parseInt(inTime[0]);
    int minute = 59 -Integer.parseInt(inTime[1]);

    feeMap.replace(key, feeMap.get(key) + 60 * hour + minute);
}

 

map의 key와 value를 다루기 위한 방법으로는 keySet(), values(), entrySet() 등 여러가지가 있다. entrySet()을 사용하여 List를 만들고, 이를 차량 번호인 key 순으로 정렬한다.

List<Map.Entry<String, Integer>> list = new ArrayList(feeMap.entrySet());
Collections.sort(list, (o1, o2) -> Integer.parseInt(o1.getKey()) - Integer.parseInt(o2.getKey()));

 

 

만약 기본 시간을 초과한 경우라면 단위 시간을 계산하며 요금을 구하고, 그렇지 않다면 기본 요금만 구한다.

answer = new int[list.size()];

for(int i = 0; i < answer.length; i++){
    if(list.get(i).getValue() > fees[0]){
        answer[i] = fees[1] + (int) Math.ceil((list.get(i).getValue() - fees[0]) / (double) fees[2]) * fees[3];
    } else{
        answer[i] = fees[1];
    }
}

 

 

전체 코드 (Java)

import java.util.*;

class Solution {
    public int[] solution(int[] fees, String[] records) {
        int[] answer = {};
        
        // 출입차를 파악하기 위한 map
        HashMap<String, String> map = new HashMap<>();
        
        // 요금을 계산하기 위한 map
        HashMap<String, Integer> feeMap = new HashMap<>();
        
        // 모든 차량의 요금을 계산하기 위한 초기값
        for(int i = 0; i < records.length; i++){
            feeMap.put(records[i].split(" ")[1], 0);
        }
        
        
        for(int i = 0; i < records.length; i++){
            String[] infos = records[i].split(" "); // 0 시간, 1 차 번호, 2 출입여부
            
            // 이미 입차한 차량이 존재해 출차를 하는 경우
            if (map.containsKey(infos[1])){
                // map에서 입차한 경우를 제거하며 입차 시간을 가져온다.
                String[] inTime = map.remove(infos[1]).split(":");
                String[] outTime = infos[0].split(":");
                
                int hour = Integer.parseInt(outTime[0]) - Integer.parseInt(inTime[0]);
                int minute = Integer.parseInt(outTime[1]) - Integer.parseInt(inTime[1]);
                
                // 요금 map에 누적 시간을 replace
                feeMap.replace(infos[1], feeMap.get(infos[1]) + 60 * hour + minute);
                
            } 
            
            // 입차하는 경우
            else {
                map.put(infos[1], infos[0]); // 차 번호, 시간
            }
        }
        
        // 아직 출차하지 않은 나머지 (23시 59분에 출차한 것으로 계산)
        for(String key : map.keySet()){
            String[] inTime = map.get(key).split(":");
            
            int hour = 23 - Integer.parseInt(inTime[0]);
            int minute = 59 -Integer.parseInt(inTime[1]);
            
            feeMap.replace(key, feeMap.get(key) + 60 * hour + minute);
        }
        
        List<Map.Entry<String, Integer>> list = new ArrayList(feeMap.entrySet());
        // Collections.sort(list, (o1, o2) -> {
        //     if(Integer.parseInt(o1.getKey()) > Integer.parseInt(o2.getKey())){
        //         return 1;
        //     } else if (Integer.parseInt(o1.getKey()) < Integer.parseInt(o2.getKey())) {
        //         return -1;
        //     } else {
        //         return 0;
        //     }
        // });
        
        Collections.sort(list, (o1, o2) -> Integer.parseInt(o1.getKey()) - Integer.parseInt(o2.getKey()));
        
        System.out.println(list);
        
        answer = new int[list.size()];
        
        for(int i = 0; i < answer.length; i++){
            if(list.get(i).getValue() > fees[0]){
                answer[i] = fees[1] + (int) Math.ceil((list.get(i).getValue() - fees[0]) / (double) fees[2]) * fees[3];
            } else{
                answer[i] = fees[1];
            }
        }
        
        return answer;
    }
}

 

 

후기

문자열 다루기, 형 변환, 코드가 길어지는 구현... 내가 제일 싫어하는 스타일의 문제였다. HashMap을 사용하여 문제에 접근하였지만 사용 시간이 이상하게 저장되어 다른 블로그의 풀이를 참고하였다. Comparator에 대해서도 헷갈리는 부분이 있어 공부하였다. 프로그래머스 상에서 코딩하면 어디가 어떻게 잘못 되었는지 확인하기 너무 어렵다. 좀 더 꼼꼼하게 풀기 위해 노력해야겠다.

 

(참고 블로그)

https://tmdrl5779.tistory.com/276

 

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

https://programmers.co.kr/learn/courses/30/lessons/92341 코딩테스트 연습 - 주차 요금 계산 [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 59

tmdrl5779.tistory.com