나의 풀이
function solution(fees, records) {
const parkingData = new ParkingData(fees, records);
return parkingData.getResult();
}
class ParkingData {
#fees;
#parkingData;
#result;
constructor(fees, records) {
this.#fees = fees;
this.records = records;
this.#parkingData = {};
this.#run();
}
#run() {
this.#calculateTotalHoursOfUse();
this.#sort();
this.#calculateFee();
}
getResult() {
return this.#result;
}
#calculateTotalHoursOfUse(carData = {}) {
this.records.forEach((record) => {
let [passTime, carNumber, inOrOut] = record.split(' ');
let [hour, minute] = passTime.split(':');
passTime = hour * 60 + +minute;
this.#parkingData[carNumber] = this.#parkingData[carNumber] ?? 0;
if (inOrOut === 'IN') return (carData[carNumber] = passTime);
this.#parkingData[carNumber] += passTime - carData[carNumber];
return (carData[carNumber] = null);
});
this.#processCarNotPulledOut(carData);
}
#processCarNotPulledOut(carData) {
const DEFULAT_OUT_TIME = 1439;
for (let carNumber in carData) {
if (carData[carNumber] !== null) {
this.#parkingData[carNumber] += DEFULAT_OUT_TIME - carData[carNumber];
}
}
}
#sort() {
this.#parkingData = Object.entries(this.#parkingData).sort(([a], [b]) => +a - +b);
}
#calculateFee() {
const [basicTime, basicFee, unitTime, unitFee] = this.#fees;
this.#result = this.#parkingData.map(([_, stayTime]) => {
let divide = (stayTime - basicTime) / unitTime;
divide < 1 ? (divide = 1) : (divide = Math.ceil(divide));
if (stayTime > basicTime) return basicFee + divide * unitFee;
return basicFee;
});
}
}
대표적으로 3가지 메서드를 만들었다.
1. calculateTotalHoursOfUse()
차량 번호에 따라 총 이용시간을 계산해서 저장해주는 메서드이다.
#calculateTotalHoursOfUse(carData = {}) {
this.records.forEach((record) => {
let [passTime, carNumber, inOrOut] = record.split(' ');
let [hour, minute] = passTime.split(':');
passTime = hour * 60 + +minute;
this.#parkingData[carNumber] = this.#parkingData[carNumber] ?? 0;
if (inOrOut === 'IN') return (carData[carNumber] = passTime);
this.#parkingData[carNumber] += passTime - carData[carNumber];
return (carData[carNumber] = null);
});
this.#processCarNotPulledOut(carData);
}
차가 입차를 하면 입차 시간을 분으로 바꿔서 저장을 해준다.
예제
// carData
{ '5961': 334, '0000': 360 }
만약 out이면 그때 parkingData에 key를 차번호를 해주고 value를 passTime - carData[carNumber]로 해준다. (out이기에 여기서 passTime은 출차 시간이다.)
그러면 this.#parkingData에는 해당 차량 번호가 key가 되고 value는 총 이용시간이 된다.
그리고 다시 해당 번호 차량의 입차 시간은 초기화 해준다.
그렇게 하면 정상적으로 입차 출차가 이루어진 차는 carData의 해당 차량 번호의 value가 null이지만
출차가 23:59까지 되지 않으면 입차 기록만 남기에 null이 아니면 전부 출차 시간을 23:59으로 간주하여 계산해주는 게 바로 for문이다.
2. sort()
차량 번호를 오름차순으로 정렬해주는 메서드이다.
여기서 객체 자체를 순서대로 정렬했다가 몇십시간을 날렸다.
객체는 정렬개념이 모호하다.
이에 대해 추후에 다시 정리할 예정이다.
일단 숫자 모양의 문자열을 객체내에서 정렬하면 "0000", "0143", 같은 경우 특히하게 자동 정렬된다.
즉 객체를 배열로 바꿔서 정렬한 뒤 reduce나 for문으로 객체를 만들어도 값을 추가한 순서대로 저장되는 게 아니라
조금 특이하게 저장된다.
sort((a,b) => a -b) 즉 내림 차순이나 오른차순, 그냥 sort()한 것과도 다르게 정렬이 된다.
단 문자열은 sort하면 정렬이 되긴 된다.
객체내의 정렬은 브라우저에 따라 다르게 값이 추가될 수도 있기에 조심해줘야한다.
https://stackoverflow.com/questions/5467129/sort-javascript-object-by-key
3.calculateFee()
차량 번호에 따라 저장된 총 이용시간을 활용하여 각각의 지불해야할 주차요금을 계산한뒤 결과값을 this.#result에 저장해준다.
다른 사람 풀이
function solution(fees, records) {
const parkingTime = {};
records.forEach(r => {
let [time, id, type] = r.split(' ');
let [h, m] = time.split(':');
time = (h * 1) * 60 + (m * 1);
if (!parkingTime[id]) parkingTime[id] = 0;
if (type === 'IN') parkingTime[id] += (1439 - time);
if (type === 'OUT') parkingTime[id] -= (1439 - time);
});
const answer = [];
for (let [car, time] of Object.entries(parkingTime)) {
if (time <= fees[0]) time = fees[1];
else time = Math.ceil((time - fees[0]) / fees[2]) * fees[3] + fees[1]
answer.push([car, time]);
}
return answer.sort((a, b) => a[0] - b[0]).map(v => v[1]);
}
개인적으로 이 코드는 가독성이 떨어지는 것 같다.
이렇게 한다면 주석이 필요할 것 같다.
특히 fees[0], fees[1] 등은 fees가 무엇인지 직접 확인해야한다.
단 이미 문제들 다 이해하고 풀어본 사람이라면 간단해서 이해하기 쉬울 것 같다.
'알고리즘 > 프로그래머스 - JS' 카테고리의 다른 글
[프로그래머스-JS] level.1 모의고사 <완전탐색> / 다시풀기o (0) | 2023.01.17 |
---|---|
[프로그래머스 - JS] level.1 과일 장수 (0) | 2023.01.15 |
[프로그래머스 - JS] level.2 귤 고르기 (0) | 2022.12.31 |
[프로그래머스] level.2 압축 (0) | 2022.12.27 |
[프로그래머스 - JS] level.2 k진수에서 소수 개수 구하기 (0) | 2022.12.26 |