[알고리즘] 프로그래머스 - 주차 요금 계산 (python)

Ben·2022년 7월 11일
0

알고리즘

목록 보기
4/10

알고리즘 문제

코딩테스트 연습 - 주차 요금 계산

  • 주차장의 요금표와 차량이 들어오고 나간 기록이 주어졌을 때, 차량 별로 주차 요금을 계산한다.
  • 어떤 차량이 입차된 후에 출차된 내역이 없다면, 23시 59분에 출차된 것으로 간주한다.
  • 하루 단위로 끊어 누적 시간을 계산하고, 누적 시간을 바탕으로 요금을 일괄로 정산한다.
  • 누적 주차 시간이 기본 요금 이하라면, 기본 요금을 청구한다.
  • 초과시간이 나누어 떨어지지 않으면, 올림한다.

키 포인트

  • 문자열 시간을 숫자로 변환하기
    • 카카오에서 자주 출제되는 유형이므로, 보일러 플레이트를 만들어서 활용하면 시간을 절약할 수 있을 것이다.
  • 누적 시간 저장 공간

해결 방법

문자열 시간을 숫자로 변환한다.

문자열로 되어있는 시간을 보고 가장 먼저 들어야 하는 생각은, 문자열의 시간을 숫자로 변환하는 것이어야 한다. 문자열 간 시간을 비교할 수 없으므로, 숫자로 변환하여 누적 분을 저장해 둔다면, 시간을 빼거나 비교하는 데 있어서 매우 편하기 때문이다.

# 문자열 시간을 포맷팅하는 코드
def get_time(time):
    s_hours, s_minutes = time.split(":")
    return int(s_hours) * 60 + int(s_minutes)

시간을 누적하여 저장한다.

시간을 저장하는 공간을 만든 뒤, records를 순회하며 시간을 누적시킨다. 이 때, 주의해야 할 점은, 들어오는 기록은 항상 존재하지만, 나가는 기록은 존재하지 않을 수 있다. 이를 어떻게 처리해야 하나 처음에는 고민을 했다.

  • 00:00 부터 23:59까지 타임라인을 만들고, 각 차량들을 표시하기: 어떤 구간 누적의 값을 구하는 것이 아니므로 의미가 없다고 생각하여 실제로 시도해보지는 않았다.

그런데 문제의 조건에 들어오는 시간에 나가는 차량의 경우는 없다고 했으므로, 해당 경우를 이용하였다.

  • 기록이 IN일 때
    • data 딕셔너리의 키의 0번째 인덱스에 숫자로 변환된 시간을 저장한다.
  • 기록이 OUT일 때
    • data 딕셔너리의 키의 1번째 인덱스에 숫자로 변환된 시간을 저장한다.
    • 1번째 인덱스의 시간 - 0번째 인덱스의 시간을 뺀 값을 별도의 공간에 저장한다.
    • 배열의 값을 23:59를 숫자로 변환한 시간으로 초기화한다.

OUT일 경우 초기화 했기 때문에 두 시간이 같을 것이고, 만약 OUT 기록이 없다면 IN과 OUT의 시간이 다를 것이기 때문에, records를 모두 순회한 뒤 data 딕셔너리의 키를 순회하여 들어오는 시간과 나가는 시간이 다를 경우에 23:59분에서 들어오는 시간을 뺀 값을 누적시간에 더한다.

요금을 구한다.

요금을 구하는 공식은 간단하다. 기본 요금 + (누적 시간 - 기본 시간 [0보다 작다면 0]) / 단위 시간의 올림 값 * 요금이다.

def get_charge(fees, diff):
    basic_time, basic_charge, unit_time, unit_charge = fees
    return (
        basic_charge
        + int(
            math.ceil((diff - basic_time if diff - basic_time > 0 else 0) / unit_time)
        )
        * unit_charge
    )

문제에 맞게 데이터를 정렬하고 가공한다.

나머지는 코드로 확인하자.

코드 보기

import math

def solution(fees, records):
    answer = []
    data = {}
    cumulative_time = {}

    last_time = get_time("23:59")
    for record in records:
        time, car, status = record.split(" ")
        if car not in data.keys():
            data[car] = [last_time, last_time]
        if status == "IN":
            data[car][0] = get_time(time)
        elif status == "OUT":
            data[car][1] = get_time(time)
            cumulative_time[car] = (
                cumulative_time.get(car, 0) + data[car][1] - data[car][0]
            )
            data[car] = [last_time, last_time]
    for key in data.keys():
        cumulative_time[key] = cumulative_time.get(key, 0) + data[key][1] - data[key][0]
    for item in cumulative_time.items():
        key, value = item
        answer.append((key, get_charge(fees, value)))
		# 데이터를 정렬하고 가공한다.
    return list(map(lambda x: x[1], sorted(answer, key=lambda x: x[0])))

def get_time(time):
    s_hours, s_minutes = time.split(":")
    return int(s_hours) * 60 + int(s_minutes)

def get_charge(fees, diff):
    basic_time, basic_charge, unit_time, unit_charge = fees
    return (
        basic_charge
        + int(
            math.ceil((diff - basic_time if diff - basic_time > 0 else 0) / unit_time)
        )
        * unit_charge
    )

느낀 점

아주 어려운 문제는 아니었지만, 중간 중간 까다로운 부분이 있었다.

  • OUT 데이터가 항상 주어지지 않아, 이를 판별하는 로직이 필요하다는 점
profile
New Blog -> https://portfolio-mrbartrns.vercel.app

0개의 댓글