thumbnail

[lv.2] 주차 요금 계산 | 프로그래머스

[lv.2] 주차 요금 계산 | 프로그래머스

📋 [ 프로그래머스 ] 시리즈 몰아보기 (17)

✏️ (lv.2) : 주차 요금 계산

주차장의 요금표와 차량이 들어오고 나간 기록이 주어졌을 때, 차량별로 주차 요금을 계산하려고 한다. 아래는 하나의 예시를 나타낸다.

  • 요금표

    기본 시간(분) 기본 요금(원) 단위 시간(분) 단위 요금(원)
    180 5000 10 600
  • 입/출차 기록

    시간(H:M) 차량 번호 내역
    05:34 5961 입차
    06:00 0000 입차
    06:34 0000 출차
    07:59 5961 출차
    07:59 0148 입차
    18:59 0000 입차
    19:09 0148 출차
    22:59 5961 입차
    23:59 5961 출차
  • 차량별 주차 요금

    차량 번호 누적 주차 시간(분) 주차 요금(원)
    0000 34 + 300 = 334 5000 + (334 - 180) / 10 _ 600 = 14600
    0148 670 5000 + (670 - 180) / 10 _ 600 = 34400
    5961 145 + 1 = 146 5000
    • 어떤 차량이 입차된 후 출차 내역이 없다면 23:59에 출차된 것으로 간주한다.
    • 00:00 ~ 23:59까지의 입/출차 내역을 바탕으로 누적 주차 시간을 계산해 요금을 일괄정산 한다.
    • 누적 주차 시간이 기본 시간 이하라면 기본 요금을 청구한다.
    • 누적 주차 시간이 기본 시간을 초과하면 기본 요금 + 초과한 시간 _ 단위 시간 _ 단위 요금을 청구한다.
      • 초과한 시간이 단위 시간으로 나누어 떨어지지 않으면 올림한다.

주차 요금을 나타내는 정수 배열 fees, 자동차의 입/출차 내역을 나타내는 문자열 배열 records가 매개변수로 주어질 때 차량 번호가 작은 자동차부터 청구할 주차 요금을 차례대로 정수 배열에 담아서 return 하는 solution 을 작성하라.


  • fees의 길이 = 4
    • fees[0] = 기본 시간(분)
    • 1 ≤ fees[0] ≤ 1,439
    • fees[1] = 기본 요금(원)
    • 0 ≤ fees[1] ≤ 100,000
    • fees[2] = 단위 시간(분)
    • 1 ≤ fees[2] ≤ 1,439
    • fees[3] = 단위 요금(원)
    • 1 ≤ fees[3] ≤ 10,000
  • 1 ≤ records의 길이 ≤ 1,000
    • records의 각 원소는 "시각 차량번호 내역" 형식의 문자열이다.
    • 시각, 차량번호, 내역은 하나의 공백으로 구분되어 있다.
    • 시각은 차량이 입차되거나 출차된 시각을 나타내며, HH:MM 형식의 길이 5인 문자열이다.
      • HH:MM은 00:00부터 23:59까지 주어진다.
      • 잘못된 시각("25:22", "09:65" 등)은 입력으로 주어지지 않는다.
    • 차량번호는 자동차를 구분하기 위한, `0'~'9'로 구성된 길이 4인 문자열이다.
    • 내역은 길이 2 또는 3인 문자열로, IN 또는 OUT이다. IN은 입차를, OUT은 출차를 의미한다.
    • records의 원소들은 시각을 기준으로 오름차순으로 정렬되어 주어진다.
    • records는 하루 동안의 입/출차된 기록만 담고 있으며, 입차된 차량이 다음날 출차되는 경우는 입력으로 주어지지 않는다.
    • 같은 시각에, 같은 차량번호의 내역이 2번 이상 나타내지 않는다.
    • 마지막 시각(23:59)에 입차되는 경우는 입력으로 주어지지 않는다.
    • 아래의 예를 포함하여, 잘못된 입력은 주어지지 않는다.
      • 주차장에 없는 차량이 출차되는 경우
      • 주차장에 이미 있는 차량(차량번호가 같은 차량)이 다시 입차되는 경우

객체를 이용해 차량의 입/출차 시간에 따른 주차 시간을 기록, 해당 객체를 순회하며 주차시간을 주어진 요금표에 맞게 정산하여 return한다.

  • 객체 parkingTime을 선언한다.
  • recordsitem으로 순회하며 다음 로직을 수행한다.
    • itemsplit(" ")으로 분리하고 각각 time, id, type으로 선언한다.
    • 이중 time을 또다시 split(":")으로 분리하고 시간(h * 60) + 분(m)으로 값을 초기화한다.
    • parkingtime[id]가 존재하지 않을 경우 해당 값을 0으로 초기화한다.
    • type === "IN"인 경우 parkingTime[id]의 값에 1439 - time을 더한 후 해당 결과값으로 초기화한다.
    • type === "OUT"인 경우 parkingTime[id]의 값에 1439 - time을 차감한 후 해당 결과값으로 초기화한다.
      • 1439 - time을 수행하는 이유는 1439(=24*60-1)이고 입차 후 출차기록이 없을 경우 해당 값을 즉시 이용하기 위해서이다. 출차가 정상적으로 진행된다면 마찬가지로 1439 - time의 값을 연산에 이용하기에 본질적으로 주차시간을 계산함에 있어서 문제가 없게된다.
  • 배열 answer을 선언한다.
  • parkingTime의 key와 value를 각각 car, time이라 선언하고 해당 값을 이용해 객체를 순회하며 다음 로직을 수행한다.
    • time {'<='} 기본 시간인 경우 time기본 요금으로 초기화한다.
    • 그렇지 않을 경우 (time - 기본 시간) / 단위 요금의 결과값을 Math.ceil()메소드를 이용해 올림연산을 수행한 후 time의 값으로 초기화한다.
    • answer에 [car, time]을 push한다.
  • answersort()메소드를 이용해 각 원소의 첫번째 값(차량 번호)를 기준으로 정렬한 후 .map()메소드를 이용해 차량요금만 추출하여 새로운 배열로 초기화 후 return 한다.
          
1 // 개선판
2 function betterSolution(fees, records) {
3 const parkingTime = {};
4 records.forEach(item => {
5 let [time, id, type] = item.split(" ");
6 let [h, m] = time.split(":");
7 time = h * 1 * 60 + m * 1;
8 if (!parkingTime[id]) parkingTime[id] = 0;
9 if (type === "IN") parkingTime[id] += 1439 - time;
10 if (type === "OUT") parkingTime[id] -= 1439 - time;
11 });
12 const answer = [];
13 for (let [car, time] of Object.entries(parkingTime)) {
14 if (time <= fees[0]) time = fees[1];
15 else time = Math.ceil((time - fees[0]) / fees[2]) * fees[3] + fees[1];
16 answer.push([car, time]);
17 }
18 return answer.sort((a, b) => a[0] - b[0]).map(v => v[1]);
19 }
20
21 // 처음 작성했던 코드
22 function solution(fees, records) {
23 const answer = [];
24 const park = new Map();
25 const parkingFee = new Map();
26 const isPark = new Map();
27
28 records.forEach(item => {
29 let [time, car, state] = item.split(" ");
30 time = time.split(":").map(e => +e);
31 time = time[0] * 60 + time[1];
32
33 if (state === "IN") {
34 park.set(car, time);
35 isPark.set(car, true);
36 } else {
37 isPark.set(car, false);
38 parkingFee.set(
39 car,
40 parkingFee.get(car) + time - park.get(car) || time - park.get(car),
41 );
42 }
43 });
44
45 for ([key, value] of isPark.entries()) {
46 if (value) {
47 parkingFee.set(
48 key,
49 parkingFee.get(key) + 24 * 60 - 1 - park.get(key) ||
50 24 * 60 - 1 - park.get(key),
51 );
52 isPark.set(key, false);
53 }
54 answer.push(key);
55 }
56
57 answer.sort((a, b) => a - b);
58 for ([car, time] of parkingFee.entries()) {
59 if (time > fees[0]) {
60 time = Math.ceil((time - fees[0]) / fees[2]);
61 answer[answer.indexOf(car)] = fees[1] + time * fees[3];
62 } else {
63 answer[answer.indexOf(car)] = fees[1];
64 }
65 }
66
67 return answer;
68 }
# 프로그래머스
# JS
# javascript
# 코딩테스트
# 알고리즘
# 구현

💡 로그인 하지 않아도 댓글을 등록할 수 있습니다!

👨‍💻 관련 포스트