Algorithm/Programmers Java

[JAVA] 프로그래머스 level2 주차 요금 계산

제우제우 2024. 7. 28. 15:05

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

 

프로그래머스

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

programmers.co.kr

코딩테스트 연습 > 2022 KAKAO BLIND RECRUITMENT > 주차 요금 계산 

 

문제 접근

구현 문제!!

 

문제의 핵심

1. records에 기록된 차량의 입/출차 내역은 시간의 오름차순 순서대로 기록 (00:00 ~ 23:59)

2. records에 기록된 차량의 입/출차 내역은 오류가 없다. 

3. records에 입차 내역은 있는데 출차 내역이 없으면 출차는 23:59에 한다

4. 하루에 입/출차를 여러번 하는 케이스가 있다 요금 정산은 매번 입/출차 마다 하는 게 아니라 하루에 전체 사용 시간을 기준으로 정산을 한다. 즉 누적 주차 시간

5. 누적 주차 시간이 기본 시간 이하라면 기본 요금 청구 

6. 누적 주차 시간이 기본 시간을 초과하면 초과한 시간에 대해서 단위 시간 마다 단위 요금 청부(올림)


문제 로직 설명 

1. func(records) 메서드  & calculate 메서드 

static HashMap<String, ArrayList<Integer>> map = new HashMap<>();

public static void func(String [] records){
    for(String target : records){
        String [] split = target.split(" ");
        int time = calculate(split[0]); // 시간 계산 
        String carNum = split[1]; // 차량 번호 
        if(map.containsKey(carNum)){
            map.get(carNum).add(time);
        }
        else{
            ArrayList<Integer> temp = new ArrayList<>();
            temp.add(time);
            map.put(carNum, temp);
        }
    }
}

 public static int calculate(String time){
    String [] split = time.split(":");
    int cur = 0;
    cur += Integer.parseInt(split[0]) * 60;  // 시
    cur += Integer.parseInt(split[1]);       // 분 
    return cur;
}

 

func 메서드는 records를 바탕으로 map 자료구조에 데이터를 넣는다.

map key: 차량번호 value: ArrayList<Integer> 입/출차 시간 

 

입/출차 시간을 calculate() 메서드를 통해서 간편하게 구했다. 

records는 시간 순서대로 들어오고 입/출차 내역엔 문제가 없으니까 

항상 입차/출차 순서대로 들어온다! 

 

2. List<String> list = func2();

List<String> list = func2();
 
public static List<String> func2(){
    ArrayList<String> list = new ArrayList<>(map.keySet());
    Collections.sort(list); // 차량 번호가 작은 자동차 순서
    return list;
}

 

map의 key를 바탕으로 차량 번호가 작은 순서대로 정렬을 해서 List를 반환한다. 

 

3. return func3(list, fees); 문제의 핵심 로직 

return func3(list, fees);

public static int [] func3(List<String> list, int [] fees){
    // fees 0: 기본시간 1: 기본요금 2: 단위시간 3: 단위요금 
    int insert = (23 * 60) + 59;
    int [] answer = new int [list.size()];
    int cnt = 0;
    for(String key : list){
        List<Integer> temp = map.get(key);
        if(temp.size() % 2 == 1) temp.add(insert);
        int fee = 0;
        int time = 0;
        for(int i = 0; i < temp.size(); i+=2){
            time += temp.get(i+1) - temp.get(i);
        }
        time -= fees[0]; // 기본시간
        fee  += fees[1]; // 기본요금     
        if(time > 0){
            fee += (time / fees[2]) * fees[3];
            if(time % fees[2] != 0){
                fee += fees[3];
            }
        }
        answer[cnt++] = fee;
    }
    return answer;
}

 

int insert 

입/출차 내역이 홀수 즉 pair를 이루지 못한다면 출차 내역이 하나가 없는 케이스이다.

이런 경우 마지막 시간을 넣어준다.(23 * 60 + 59) == (23:59) 

 

차량 번호가 작은 순서대로 (for String key : list) 를 돌면서 요금 정산을 한다. 

해당 차량 번호의 입/출차 내역이 홀수인 경우 미리 정의한 insert를 리스트에 넣는다. 

int insert = (23 * 60) + 59;

 

각 구간마다 시간을 구한다 구간이란 출차 - 입차 시간 

이런 구간을 모두 더해서 해당 차량 번호의 누적 주차 시간을 구한다. 

int time = 0;
for(int i = 0; i < temp.size(); i+=2){
    time += temp.get(i+1) - temp.get(i);
}

 

요금 정산 로직 

먼저 기본요금을 계산한다. 

기본 금을 계산하고 그래도 시간이 남는다면 단위 시간으로 초과 요금을 계산한다

이때 나머지 즉 나누어떨어지지 않는 시간은 올림 처리한다. 

time -= fees[0]; // 기본시간
fee  += fees[1]; // 기본요금     
if(time > 0){
    fee += (time / fees[2]) * fees[3];
    if(time % fees[2] != 0){
        fee += fees[3];
    }
}

 


정답 코드 

import java.util.*;
class Solution {
    static HashMap<String, ArrayList<Integer>> map = new HashMap<>();
    public int[] solution(int[] fees, String[] records) {
        func(records); 
        List<String> list = func2();
        return func3(list, fees);
    }
    public static void func(String [] records){
        for(String target : records){
            String [] split = target.split(" ");
            int time = calculate(split[0]); // 시간 계산 
            String carNum = split[1]; // 차량 번호 
            if(map.containsKey(carNum)){
                map.get(carNum).add(time);
            }
            else{
                ArrayList<Integer> temp = new ArrayList<>();
                temp.add(time);
                map.put(carNum, temp);
            }
        }
    }
    public static int calculate(String time){
        String [] split = time.split(":");
        int cur = 0;
        cur += Integer.parseInt(split[0]) * 60;  // 시
        cur += Integer.parseInt(split[1]);       // 분 
        return cur;
    }
    
    public static List<String> func2(){
        ArrayList<String> list = new ArrayList<>(map.keySet());
        Collections.sort(list); // 차량 번호가 작은 자동차 순서
        return list;
    }
    
    public static int [] func3(List<String> list, int [] fees){
        // fees 0: 기본시간 1: 기본요금 2: 단위시간 3: 단위요금 
        int insert = (23 * 60) + 59;
        int [] answer = new int [list.size()];
        int cnt = 0;
        for(String key : list){
            List<Integer> temp = map.get(key);
            if(temp.size() % 2 == 1) temp.add(insert);
            int fee = 0;
            int time = 0;
            for(int i = 0; i < temp.size(); i+=2){
                time += temp.get(i+1) - temp.get(i);
            }
            time -= fees[0]; // 기본시간
            fee  += fees[1]; // 기본요금     
            if(time > 0){
                fee += (time / fees[2]) * fees[3];
                if(time % fees[2] != 0){
                    fee += fees[3];
                }
            }
            answer[cnt++] = fee;
        }
        return answer;
    }
}