개발자취

Programmers | Lv.2 / 주차 요금 계산 본문

개발/Dev | 코딩테스트

Programmers | Lv.2 / 주차 요금 계산

hnhnhun 2023. 7. 5. 00:10

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

프로그래머스

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

programmers.co.kr

주차요금 계산 문제를 풀고 나서 생각해보면 너무 간단한 건데, 자꾸 실수하는 내용이 있어서 이를 기록하기 위해서 글로 남긴다.
 

1. 문제 요약

이 문제를 요약해보면 다음과 같다.
1) 주차장의 요금표와 차량이 들어오고 나간 기록이 input 데이터로 주어짐(단, 차량 출입 기록에 들어온 기록만 있는 경우에는 23:59에 출차한 것으로 간주.)
2) 차량별로 주차 요금을 계산(단, 주차요금 계산 시 단위요금을 계산하는데, 단위 요금 계산에서 발생하는 소수 계산은 올림으로 처리.) 
3) 차량번호가 작은 값을 가진 차량 순으로 정렬해서 반환(오름차순)
입력 데이터는 fees, records이다. fees는 위 내용처럼 주차장의 요금표 이고,  records는 차량의 출입 기록이다. 문제가 너무 길게 보이긴 하지만, HashMap을 사용해서 각 차량 번호를 Key값으로 하여 차량의 출입 시간을 Value로 만들면 생각보다 수월하게 풀 수 있다. 
 

2. 로직

2-1) 로직 플로우
차량 번호를 HashMap의 key값으로 정하고, 차량의 입차/출차 시간을 value로 정한다. 그리고 나서 HashMap에 대응시킨 값을 key들만 따로 빼내서 오름차순으로 정렬하고, 그 순서에 맞게 HashMap에서 key에 매핑되는 value인 출차시간을 불러온다. 이때 value의 개수가 홀수인 경우에는 출차 시간이 없는 것이므로 23:59를 value에 추가한다. 그리고 나서 ArrayList에 담긴 차량 번호들을 하나씩 불러오는 형식으로 계산을 진행한다.(queue가 빈 상태가 될 때까지) 각 차량마다 누적 주차시간을 모두 계산한다.  주차 요금은 문제에서 준 식에 맞춰서 계산하고, 이 때 주의할 점은 단위요금 계산에서 발생하는 소수 처리인데, Math의 ceil을 사용해서 올림으로 계산한다. 차량들의 주차요금은 answer 정수타입 배열에 담아서 답으로 반환한다.
2-2) 로직 상세
1) HashMap을 생성하고, 이때 key, value의 각 타입을 String, Queue로 잡는다. 처음에는 Queue 대신 ArrayList를 사용하려 했으나, 계산 과정에서 계산한 값은 삭제하는 형식으로 푸는 게 더 낫겠다고 싶어서 바꿨다. 그리고는 HashMap의 자동차의 출차 기록을 value로 추가해준다. 이로써 입력된 records 데이터를 가공하는 작업은 끝났다. 
2) HashMap에서 key 값에 대응시킬 tempList(ArrayList)를 생성한다. (리스트는 map의 keySet 메서드로 초기화 한다.)
3) 차량 번호를 오름차순으로 정렬한다. (생성한 순간부터 차량번호가 정렬된 리스트를 계속 사용할 것이다.)
4) 계산에 사용될 total이라는 배열을 선언한다. (정수 타입 배열) 
5) ArrayList에 매핑된 차량번호를 인덱스로 접근해서 불러오고, 그 값을 key 값으로 하는 value를 불러온다. 그런데 이때 value의 길이를 체크해준다. 그래서 value가 홀수인 경우에는 입차-출차 쌍이 맞지 않는 경우니, 23:59를 출차시간으로 추가한다.
6) 누적주차시간을 계산한다. 이때 시간:분 구조에서는 String의 split 메서드를 사용하여 배열로 구분해주고, 24시간 형태이므로 계산하기 수월하게 분으로 통일시켜준다. (N시간 * 60분 = 60N분) 입차 시간과 출차 시간의 차이를 total 배열에 각 인덱스마다 누적해서 계산해준다. 이때 queue가 빈 상태가 될 때까지 계산이 진행된다.
7) total 배열에 인덱스로 접근하여 값을 가져온다. 그리고 주차 요금을 계산한다. 
** 내가 자주 실수하는 부분은 여기다. double과 double의 계산 결과는 double이고, int와 int의 계산 결과는 int라는 점을 명심하자.**
8) 계산 결과를 total 배열에 다시 담아준다. 그리고 answer의 객체를 초기화한 뒤 total 배열을 할당한 뒤 이를 반환한다.
 

3. 구현

import java.util.*;
class Solution {
    public int[] solution(int[] fees, String[] records) {
        int[] answer = {};
        HashMap<String, Queue<String>> map = new HashMap<>();
        for(String s:records){
            String[] tempArr = s.split(" ");
            if(map.get(tempArr[1]) == null) {
                map.put(tempArr[1], new LinkedList<>());
            } 
            map.get(tempArr[1]).add(tempArr[0]);
        }
        
        ArrayList<String> tempList = new ArrayList<>(map.keySet());
        Collections.sort(tempList);
        int[] total = new int[map.size()];
        
        int cnt=0;
        for(Object s:tempList.toArray()){
            if(map.get(s).size()%2 == 1){
                map.get(s).add("23:59");
            }
            
            while(!map.get(s).isEmpty()){
                String in = (String)map.get(s).poll();
                String out = (String)map.get(s).poll();
                
                int tIn = Integer.parseInt(in.split(":")[0]) * 60 + Integer.parseInt(in.split(":")[1]);
                int tOut = Integer.parseInt(out.split(":")[0]) * 60 + Integer.parseInt(out.split(":")[1]);

                total[cnt] += tOut - tIn;
            }
            cnt++;
        }
        
        for(int i=0; i<total.length; i++){
            total[i] = (total[i] > fees[0]) ? fees[1] + (int)Math.ceil((double)(total[i] - fees[0])/(double)fees[2]) * fees[3] : fees[1];
        }
        
        answer = new int[map.size()];
        answer = total;
        
        return answer;
    }
}

 

4. 결과

 
풀이 내용과 관련하여 궁금하신 점은 댓글에 남겨주시면 감사드리겠습니다. :)

Comments