출처
https://programmers.co.kr/learn/courses/30/lessons/92341
문제
주차 요금을 나타내는 정수 배열 fees, 자동차의 입/출차 내역을 나타내는 문자열 배열 records가 매개변수로 주어집니다. 차량 번호가 작은 자동차부터 청구할 주차 요금을 차례대로 정수 배열에 담아서 return 하도록 solution 함수를 완성해주세요.
제한사항
- records는 하루 동안의 입/출차된 기록만 담고 있으며, 입차 된 차량이 다음날 출차되는 경우는 입력으로 주어지지 않습니다.
- 같은 시각에, 같은 차량번호의 내역이 2번 이상 나타내지 않습니다.
- 마지막 시각(23:59)에 입차 되는 경우는 입력으로 주어지지 않습니다.
- 아래의 예를 포함하여, 잘못된 입력은 주어지지 않습니다.
- 주차장에 없는 차량이 출차되는 경우
- 주차장에 이미 있는 차량(차량번호가 같은 차량)이 다시 입차 되는 경우
풀이
records 배열에는 "시각 차량번호 출차 여부"의 정보가 담겨있습니다.
해당 정보로 차량이 주차장에 머문 총시간을 구하여 요금을 계산하면 되는 문제입니다.
let [time, car, type] = v.split(" ");
const [hour, minute] = time.split(":");
// 분으로 바꾸기
time = hour * 60 + Number(minute);
records의 각 정보를 split 메서드를 이용하여 각 시각, 차량번호, 출차 여부 정보로 나눠주고 시각 정보는 HH:MM 주어지는 시각 정보를 분으로 바꿔줍니다.
if (type == "OUT") {
cars[car].time += time - cars[car].lastInTime;
return;
}
cars[car].lastInTime = time;
객체에 각 차량의 현재 정보를 저장하여 해당 차량 번호로 간단히 정보를 가져올 수 있게 만들어줍니다.
차량이 들어왔을 때(IN)는 최근에 들어온 시각을 저장해주고, 차량이 나갔을 때(OUT)는 현재 시각에서 미리 저장한 최근에 들어온 시각을 뺀 수(주차장에 머문 시간) 만을 누적시켜줍니다.
Object.values(cars)
.sort((a, b) => a.car - b.car)
.map(v => {
// 차량이 최종적으로 나가지 않았을 때
if (v.type == "IN") {
v.time += 1439 - v.lastInTime;
}
});
모든 정보를 활용해 차량별로 누적 이용시간을 구했으면, 해당 시간에 수식을 사용하여 주차 요금 값으로 바꿔줍니다.
주차 요금 값으로 바꾸기 전에 차량 번호순으로 정렬을 해주고, 각 차량별로 다시 한번 반복문을 돌려줍니다.
이때 마지막 차량 출하 여부가 (IN)인 경우 아직 주차장에 머물러 있다는 뜻이므로 23:59에서 최근에 들어온 시각을 뺀 값을 추가로 더해줍니다.
// 기본시간을 넘지 않았을 때
if (fees[0] > v.time) {
return fees[1];
}
return fees[1] + Math.ceil((v.time - fees[0]) / fees[2]) * fees[3];
이제 fees 정보에 담겨있는 [ 기본 시간, 기본 금액, 시간 단위(분), 금액 단위 ] 값을 활용하여 금액을 정해줍니다.
만약 주차장 이용 시각이 기본 시간을 넘지 않았다면 기본 금액을 반환해주고, 시간을 넘었다면 기본 금액에 추가로 넘은 시간 단위에 금액 단위를 곱하여 추가 요금을 부과해줍니다.
코드
function solution(fees, records) {
const cars = {};
records.forEach(v => {
// 정보 쪼개기
let [time, car, type] = v.split(" ");
const [hour, minute] = time.split(":");
// 분으로 바꾸기
time = hour * 60 + Number(minute);
// 처음 조회되는 차량일 시
if (!cars[car]) {
cars[car] = { time: 0, car };
}
cars[car].type = type;
if (type == "OUT") {
cars[car].time += time - cars[car].lastInTime;
return;
}
cars[car].lastInTime = time;
});
return Object.values(cars)
.sort((a, b) => a.car - b.car)
.map(v => {
// 차량이 최종적으로 나가지 않았을 때
if (v.type == "IN") {
v.time += 1439 - v.lastInTime;
}
// 기본시간을 넘지 않았을 때
if (fees[0] > v.time) {
return fees[1];
}
return fees[1] + Math.ceil((v.time - fees[0]) / fees[2]) * fees[3];
});
}