티스토리 뷰
https://school.programmers.co.kr/learn/courses/30/lessons/92341
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
🤔 해결방법
1. 입출차 기록을 자동차 번호 기준으로 오름차순 정렬하고 자동차 번호만 추출한다.
2. for문을 돌며 자동차 번호 별 입차, 출차 시간을 계산하는데, 출차까지 한 경우와 입차만 한 경우로 나눠 계산한다.
3. 기본 시간을 기준으로 주차 요금을 계산하고 answer에 차례로 push 한다.
🔑 풀이
먼저 입출차 기록을 관리하기 쉽게 이중 배열로 저장했다.
그리고 차량 번호가 작은 자동차부터 청구할 주차 요금을 차례대로 출력해야 하기 때문에 자동차 번호를 기준으로 오름차순 정렬을 했다.
// 이중 배열로 저장
let arr = [];
for (let i = 0; i < records.length; i++) {
const [time, number, act] = records[i].split(" ");
arr.push([time, Number(number), act]);
}
// 기록 오름차순 정렬
const record = arr.sort((a, b) => a[1] - b[1]);
또한 각 기록을 자동차 별로 확인하기 위해 자동차 번호만 중복 제거하여 추출해 오름차 순으로 cars 배열에 담았다.
// 차량 번호만 추출 및 오름차순 정렬
const cars = Array.from(new Set(arr.map((item) => item[1]))).sort(
(a, b) => a - b
);
이후 누적 주차 시간을 for문을 돌며 계산한다.
이 때, 출차까지 한 경우와 입차만 한 경우로 나누어 계산해야 한다.
이미 오름차순으로 정렬했기 때문에 출차까지 한 경우는 그 다음 기록의 차 번호가 같을 것이다.
이런 경우 출차에 해당하는 다음 기록의 시간과 입차에 해당하는 현재 기록 사이의 시간을 구한다.
시간에는 60을 곱하고 거기에 분을 더해 총 시간을 분으로 환산하는 방법을 썼는데 string으로 들어가 있기에 number로 바꿔서 계산해야 한다.
이렇게 되면 출차까지 한 경우는 계산이 완료되었으니 i에 2를 더해 그 다음 입차 기록으로 넘어가게 해주면 된다.
만약 출차 기록이 없는 경우, 즉 입차만 한 경우는 입차 기록부터 23시59분까지의 시간을 계산해주면 된다.
23시에 60을 곱하고 59분을 더해주면 1439분이 되므로 1439에서 입차 시각을 빼주고 i를 1증가시켜 다음 기록으로 넘어간다.
// 출차도 한 경우
if (i < record.length - 1 && record[i + 1][1] === car) {
minutes +=
Number(record[i + 1][0].slice(0, 2)) * 60 +
Number(record[i + 1][0].slice(3, 5)) -
(Number(record[i][0].slice(0, 2)) * 60 +
Number(record[i][0].slice(3, 5)));
i += 2;
// 입차만 한 경우
} else {
minutes +=
1439 -
(Number(record[i][0].slice(0, 2)) * 60 +
Number(record[i][0].slice(3, 5)));
i++;
}
이후 기본 시간을 기준으로 주차 요금을 계산하고 answer에 차례로 push하여 출력하면 된다.
// 주차 요금 계산
if (minutes < fees[0]) {
answer.push(fees[1]);
} else {
let fee = fees[1] + Math.ceil((minutes - fees[0]) / fees[2]) * fees[3];
answer.push(fee);
}
최종 코드는 다음과 같다.
function solution(fees, records) {
let answer = [];
// 이중 배열로 저장
let arr = [];
for (let i = 0; i < records.length; i++) {
const [time, number, act] = records[i].split(" ");
arr.push([time, Number(number), act]);
}
// 기록 오름차순 정렬
const record = arr.sort((a, b) => a[1] - b[1]);
// 차량 번호만 추출 및 오름차순 정렬
const cars = Array.from(new Set(arr.map((item) => item[1]))).sort(
(a, b) => a - b
);
// 누적 주차 시간 계산
for (let car of cars) {
let minutes = 0;
for (i = 0; i < record.length; ) {
if (record[i][1] === car) {
// 출차도 한 경우
if (i < record.length - 1 && record[i + 1][1] === car) {
minutes +=
Number(record[i + 1][0].slice(0, 2)) * 60 +
Number(record[i + 1][0].slice(3, 5)) -
(Number(record[i][0].slice(0, 2)) * 60 +
Number(record[i][0].slice(3, 5)));
i += 2;
// 입차만 한 경우
} else {
minutes +=
1439 -
(Number(record[i][0].slice(0, 2)) * 60 +
Number(record[i][0].slice(3, 5)));
i++;
}
} else {
i++;
}
}
// 주차 요금 계산
if (minutes < fees[0]) {
answer.push(fees[1]);
} else {
let fee = fees[1] + Math.ceil((minutes - fees[0]) / fees[2]) * fees[3];
answer.push(fee);
}
}
return answer;
}
시간을 분으로 환산하는 부분이 반복이 많아 더 좋은 방법을 생각해봤다.
다음과 같이 함수를 따로 생성해서 사용한다면 훨씬 가독성이 좋아질 것 같다.
// 시간을 분으로 변환
const timeToMinutes = (time) => {
const [hour, minute] = time.split(":");
return Number(hour) * 60 + Number(minute);
};
'JS-algorithm > 프로그래머스' 카테고리의 다른 글
[프로그래머스] 전력망을 둘로 나누기 (javascript) (0) | 2023.10.06 |
---|---|
[프로그래머스] 다리를 지나는 트럭 (javascript) (0) | 2023.09.22 |
[프로그래머스] 주식가격 (javascript) (0) | 2023.09.15 |