[Algorithm] 주차 요금 계산

MODAC·2023년 11월 8일
0

Algorihtm

목록 보기
1/12

문제설명

주차 요금 계산은 주어진 요금표와 차량 기록을 계산하여 차 번호 순으로 요금을 반환하는 문제이다. 어려운 알고리즘은 없지만 분 단위로 치환한 후 각 차량번호에 매핑한 후 사용시간을 합산하여 기본요금 혹은 기본요금에 추가요금을 합산한 값을 구하는 과정과 출차 기록이 없을 경우 23:59분을 기준으로 요금을 더해줘야 하는 예외 처리로 인해 난이도가 올라가는 문제이다.

문제해결

처음 문제를 읽고 접근할 때 키(차량번호)와 값(사용시간)을 구하는 것이 문제 풀이의 핵심이라고 생각했다.
Set과 Map을 그 동안 몇 번 사용해봤기 때문에 개념은 어렴풋이 알고 있었지만 이런 키와 쌍의 값을 저장하고 중복을 방지하기에는 Map이 적절한 자료구조라는 부분을 다시 깨닫았다.
또한 string 형태로 주어지는 배열을 분해 후 형변환하여 시간과 요금을 계산하는 과정은 오탈자나 연산 처리에 실수가 있으면 아예 다른 값이 나와 오류 핸들링이 어려워서 까다롭게 작성했다.

1차 풀이

00:00시에 입차한 후 출차 기록이 없는 경우에 대해서 예외처리를 하지 않았다.

function solution(fees, records) {
  const parking = new Map();
  const [bTime, bFee, uTime, uFee] = fees;

  for (let i = 0; i < records.length; i++) {
    let [time, car, status] = records[i].split(" "),
      [hour, minute] = time.split(":");
    time = 60 * Number(hour) + Number(minute);
    if (status === "IN") {
      parking.set(car, {
        total: parking.has(car) ? parking.get(car).total : 0,
        time,
      });
    } else if (status === "OUT") {
      const parkTime = parking.get(car);
      const spandTime = time - parkTime.time;
      parkTime.total += spandTime;
      parkTime.time = 0;
      parking.set(car, parkTime);
    }
  }
  for (let [car, parkTime] of parking) {
    let { total, time } = parkTime;
    if (time > 0) {
      total += 23 * 60 + 59 - time;
      parking.set(car, { total, time: 0 });
    }
  }
  return [...parking]
    .sort((a, b) => a[0] - b[0])
    .map(([_, { total, time }]) =>
      total <= bTime ? bFee : bFee + Math.ceil((total - bTime) / uTime) * uFee
    );
}

2차 풀이

function solution(fees, records) {
  const parking = new Map();
  const [bTime, bFee, uTime, uFee] = fees;

  for (let i = 0; i < records.length; i++) {
    let [time, car, status] = records[i].split(" "),
      [hour, minute] = time.split(":");
    time = 60 * Number(hour) + Number(minute);
    if (status === "IN") {
      parking.set(car, {
        total: parking.has(car) ? parking.get(car).total : 0,
        time,
      });
    } else if (status === "OUT") {
      const parkTime = parking.get(car);
      const spandTime = time - parkTime.time;
      parkTime.total += spandTime;
      parkTime.time = 0;
      parking.set(car, parkTime);
    }
  }

  for (let [car, parkTime] of parking) {
    let { total, time } = parkTime;
    // 첫 입차 후 출차하지 않았거나 차량의 마지막 기록 이후 출차하지 않은 경우
    if (time > 0 || total <= 0) {
      total += 23 * 60 + 59 - time;
    }
    // 모든 차량의 입출차 처리 후 가격 계산 - 기본요금 혹은 추가요금 + 기본요금
    const fee =
      total <= bTime ? bFee : bFee + Math.ceil((total - bTime) / uTime) * uFee;
    // 저장된 시간 객체를 전체요금으로 형변환 후 값으로 재할당
    parking.set(car, fee);
  }
  return [...parking].sort((a, b) => a[0] - b[0]).map((e) => e[1]);
}

1개의 댓글

comment-user-thumbnail
2023년 11월 8일

잘푸셨네요!

답글 달기