Algorithm/Algorithm Test

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

MarrRang 2022. 8. 17. 23:32

카테고리

알고리즘

나만의 카테고리

알고리즘

문제 링크

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

 

프로그래머스

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

programmers.co.kr

요점

  • 알맞은 로직 짜기
  • 적당한 자료 구조 사용
  • for문으로 iteration에 사용되는 객체를 for문 안에서 제거하지 않도록 주의 (런타임 에러)

참고 지식

  • Map, Set
  • Map Sort 하기

풀이 (Java)

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.time.format.DateTimeFormatter;

class Solution {
    Map<String, LocalDateTime> inCarMap = new HashMap<>();
    Map<String, Integer> accumCarMap = new HashMap<>();
    Map<String, Integer> carFeeMap = new HashMap<>();
    
    int baseTime = 0;
    int baseFee = 0;
    int perTime = 0;
    int perFee = 0;
    
    public int[] solution(int[] fees, String[] records) {
        // 기본 가격 세팅
        setBaseFee(fees);
        
        // 기본 시간 계산
        for (String record : records) {
            String[] sptRecords = record.split(" ");
            
            if (sptRecords[2].equals("IN")) {
                inCar(sptRecords[1], sptRecords[0]);
            } else if (sptRecords[2].equals("OUT")) {
                outCar(sptRecords[1], sptRecords[0]);
            }
        }
        
        // 23:59 출차 차량 시간 계산
        calLastOutCarFee();
        
        // 요금 계산
        calFee();
        
        // 번호 작은 차량 순서로 정렬된 결과
        int[] answer = sortByCarNumber();
        
        return answer;
    }
    
    public void setBaseFee(int[] fees) {
        baseTime = fees[0];
        baseFee = fees[1];
        perTime = fees[2];
        perFee = fees[3];
    }
    
    public void inCar(String carNumber, String time) {
        LocalDateTime lTime = LocalDateTime.parse("2022-01-01 " + time, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
        
        inCarMap.put(carNumber, lTime);
    }
    
    public void outCar(String carNumber, String time) {
        LocalDateTime lTime = LocalDateTime.parse("2022-01-01 " + time, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
                
        int defTime = (int)ChronoUnit.MINUTES.between(inCarMap.get(carNumber), lTime);
        
        accumCarMap.put(carNumber, Optional.ofNullable(accumCarMap.get(carNumber)).orElse(0) + defTime);
        
        inCarMap.remove(carNumber);
    }
    
    public void calLastOutCarFee() {
        Set<Map.Entry<String, LocalDateTime>> tempSet = new HashSet<>();
        tempSet.addAll(inCarMap.entrySet());
        
        for (Map.Entry<String, LocalDateTime> each : tempSet) {
            outCar(each.getKey(), "23:59");
        }
    }
    
    public void calFee() {
        for (Map.Entry<String, Integer> each : accumCarMap.entrySet()) {
            int defTime = each.getValue();
        
            int fee = baseFee;
        
            if (defTime > baseTime) {
                int rest = ((defTime - baseTime) % perTime) > 0 ? 1 : 0;
                
                fee = fee + (int)(((defTime - baseTime) / perTime + rest) * perFee);
            }
        
            carFeeMap.put(each.getKey(), fee);
        }
    }
    
    public int[] sortByCarNumber() {
        List<Map.Entry<String, Integer>> feeEntries = new LinkedList<>(carFeeMap.entrySet());
        Collections.sort(feeEntries, (o1, o2) -> o1.getKey().compareTo(o2.getKey()));
        
        int[] result = new int[feeEntries.size()];
        
        for (int i = 0; i < feeEntries.size(); i++) {
            result[i] = feeEntries.get(i).getValue();
        }
        
        return result;
    }
}

 

이 문제는 특별한 기법을 적용해야 한다기 보다는 그냥 로직을 알맞게 짤 수 있는지를 확인하는 문제인 것 같습니다.

시간 단축을 위해 좀 어지럽게 풀긴 했지만 위와 같이 main에서 각각 함수로 나누어서 작성하면 나중에 에러가 발생했을 때 주석처리하며 에러를 찾기가 쉬워집니다.

 

프로그래머스의 문제 질문하기의 글 중에 있는 주의점으로는 Map을 사용해서 풀 경우 for문에서 사용되는 객체를 for문 안에서 건드리는 로직이 불가피한 것 같습니다. 이를 주의하지 않으면 몇몇 테스트 케이스에서 런타임 에러가 발생합니다.

 


알고리즘 초보가 정리한 글입니다

더 좋은 방법이나 코드에 대한 코멘트 언제나 환영합니다!

 

 

 

반응형