프로그래머스 2022 KAKAO BLIND RECRUITMENT Level 2 문제 주차 요금 계산 을 Java를 이용해 풀어보았다.
풀면서 좀 깔끔하게 정돈이 되지 않는 느낌이라 욱여 푸는 느낌으로 풀었다.
문제링크 첨부한다.
https://programmers.co.kr/learn/courses/30/lessons/92341
차량 번호와 그에 따른 출입 기록을 저장하기 위해 HashMap을 이용했다. 차량 번호를 String으로 Key값으로 설정했고, Info라는 클래스를 정의해서 Value로 설정했다.
먼저 Info 클래스의 구성을 살펴보자.
Info 클래스
1. 출입 기록 ( Queue ) : 변수
2. 주차 요금 ( int ) : 변수
3. 주차 요금 계산 ( void ) : 메소드
class Info{
Queue<Time> record = new LinkedList<>();
int totalBill;
Info(Time a){ record.add(a); }
void getTotalBill(int defaultTime, int defaultBill, int unitTime, int unitBill){
int result = 0;
int totalMins = 0;
Time before = new Time(0,0);
Time after = new Time(0,0);
while(!this.record.isEmpty()){
if(this.record.size()!=1) before = this.record.poll();
else break;
after = this.record.poll();
Time lap = after.getLap(before);
totalMins += lap.hrs*60 + lap.mins;
}
if(!this.record.isEmpty()){
Time last = this.record.poll();
Time lap = new Time(23, 59).getLap(last);
totalMins += lap.hrs*60 + lap.mins;
}
if(totalMins<=defaultTime) result += defaultBill;
else {
result += defaultBill;
totalMins -= defaultTime;
int unitCnt = (totalMins % unitTime == 0 ? totalMins / unitTime : totalMins / unitTime + 1);
result += unitCnt * unitBill;
}
this.totalBill = result;
}
}
각 차량 별로 출입 기록을 저장해야 하며, 그에 따른 주차 요금이 존재한다. 이 때 출입 기록에 따라 주차 요금을 계산해주는 메소드도 필요하기에 위의 세 가지 구성 요소들이 나온 것이다.
우선은 차량 번호에 따라 출입 기록을 문제에서 주어진 String[] records
를 통해 받는 과정이 우선이고, 정보를 다 받은 후에 주차 요금 계산이 이루어 지면 된다.
먼저 String[] records
를 통해 출입 기록 정보를 받는 단계를 살펴보자.
HashMap<String, Info> map = new HashMap<>();
for(String record: records){
StringTokenizer stk = new StringTokenizer(record);
String[] time = stk.nextToken().split(":");
String carNum = stk.nextToken();
int hrs = Integer.parseInt(time[0]);
int mins = Integer.parseInt(time[1]);
Time tmp = new Time(hrs, mins);
if(map.get(carNum)==null) // 아직 이 번호의 차량 정보가 없으면
map.put(carNum, new Info(tmp));
else // 이미 이 차량의 전적이 있으면
map.get(carNum).record.add(tmp);
}
출입 기록을 다 입력 받았으니 전체 주차 요금을 계산하면 된다.
for(Info a: map.values()){
a.getTotalBill(defaultTime,defaultBill,unitTime,unitBill);
}
getTotalBill()
메소드는 앞서 Info 클래스를 살펴볼 때 나왔었는데, 간단히 말하면 주차한 총 시간을 계산한 후 그에 따른 주차 요금을 문제 조건대로 계산해주는 작업을 해주는 메소드다. 그냥 조건대로 구현하는 거라 특별한 로직이 필요하진 않아서 따로 설명을 붙이진 않는다.
문제에서 차량 번호를 오름차순으로 정렬해서 주차 요금 결과를 반환하라고 했다. 먼저 map
의 key값들을 정렬해서 그 key 값들 배열에 따라 map
에서 주차 요금만 뽑아와서 answer
배열에 저장해주면 된다. 코드로 표현하면 다음과 같다.
Object[] mapKey = map.keySet().toArray();
Arrays.sort(mapKey);
int[] answer = new int[map.size()];
int i = 0;
for(Object key: mapKey){
answer[i] = map.get(key).totalBill;
i++;
}
return answer;
위의 모든 코드들을 합치면 다음과 같다. 내가 제출한 코드다.
import java.io.*;
import java.util.*;
public class ParkingBill {
static int[] solution(int[] fees, String[] records) {
int defaultTime = fees[0]; int defaultBill = fees[1];
int unitTime = fees[2]; int unitBill = fees[3];
HashMap<String, Info> map = new HashMap<>();
for(String record: records){
StringTokenizer stk = new StringTokenizer(record);
String[] time = stk.nextToken().split(":");
String carNum = stk.nextToken();
int hrs = Integer.parseInt(time[0]);
int mins = Integer.parseInt(time[1]);
Time tmp = new Time(hrs, mins);
if(map.get(carNum)==null)
map.put(carNum, new Info(tmp));
else
map.get(carNum).record.add(tmp);
}
for(Info a: map.values()){
a.getTotalBill(defaultTime,defaultBill,unitTime,unitBill);
}
Object[] mapKey = map.keySet().toArray();
Arrays.sort(mapKey);
int[] answer = new int[map.size()];
int i = 0;
for(Object key: mapKey){
answer[i] = map.get(key).totalBill;
i++;
}
return answer;
}
static class Info{
Queue<Time> record = new LinkedList<>();
int totalBill;
Info(Time a){ record.add(a); }
void getTotalBill(int defaultTime, int defaultBill, int unitTime, int unitBill){
int result = 0;
int totalMins = 0;
Time before = new Time(0,0);
Time after = new Time(0,0);
while(!this.record.isEmpty()){
if(this.record.size()!=1) before = this.record.poll();
else break;
after = this.record.poll();
Time lap = after.getLap(before);
totalMins += lap.hrs*60 + lap.mins;
}
if(!this.record.isEmpty()){
Time last = this.record.poll();
Time lap = new Time(23, 59).getLap(last);
totalMins += lap.hrs*60 + lap.mins;
}
if(totalMins<=defaultTime) result += defaultBill;
else {
result += defaultBill;
totalMins -= defaultTime;
int unitCnt = (totalMins % unitTime == 0 ? totalMins / unitTime : totalMins / unitTime + 1);
result += unitCnt * unitBill;
}
this.totalBill = result;
}
}
static class Time{
int hrs;
int mins;
Time(int hrs, int mins){
this.hrs = hrs;
this.mins = mins;
}
Time getLap(Time before){
if(this.mins - before.mins >=0) return new Time(this.hrs-before.hrs, this.mins- before.mins);
else return new Time(this.hrs-before.hrs-1, this.mins- before.mins+60);
}
}
public static void main(String[] args) throws IOException {
BufferedWriter bfw = new BufferedWriter(new OutputStreamWriter(System.out));
int[] fees = { 180, 5000, 10, 600 };
String[] records = { "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 5961 IN", "23:00 5961 OUT" };
int[] answer = solution(fees, records);
}
}
풀면서 뭔가 깔끔하게 정돈되지 않는 느낌이 강했다. 문제 조건대로 쭉 따라가면 되긴 하는데 전체 설계를 엉성하게 하고 들어가니 어떻게든 결과만 나오도록 끼워맞추는 식의 풀이가 되어버려서 시간도 한없이 늘어졌다.
앞으로는 문제를 풀 때 아무리 쉬운 문제라도, 어떤 클래스를 정의할 것이며 어떤 메소드를 어디에 정의해서 어디서 사용할 건지 대략적인 빌드를 치고 본격적인 코드 작성에 들어가는 습관을 들여보면 훨씬 효율이 높아질 것 같다.