[프로그래머스] 주차 요금 계산 - Python

Rachel·2024년 4월 25일
1

Algorithm

목록 보기
6/10

오늘 한국조폐공사 코테를 응시했다.
2시간에 총 3문제였고, 내가 푼 문제가 맞았다면 3문제 중에 2문제를 풀었다.
상대적으로 엄청나게 어려운 코테는 아니였지만 보기 전에 응시환경 세팅도 하고 셤에 몰입하다 보니 하루 에너지를 여기 많이 쓴 것 같다.
밤에 예정되어 있는 코테 스터디에 겨우 가서 1문제 풀이를 할 수 있었다.

예전에 이런 긴 코테 문제를 보면 아예 무슨 유형인지 파악이 잘 안되고 풀 엄두도 안났는데, 지금은 공부한 유형이라면 유형이 좀 보이고 다른 사람 풀이를 참고하거나 내가 풀고 나서 더 나은 풀이가 뭘까 생각할 수 있는 정도로 성장한 것 같다.

문제

프로그래머스 주차 요금 계산 - 2022 KAKAO BLIND RECRUITMENT

풀이

  • 처음 코드
# 입차 후 출차 내역이 없다면 23:59에 출차된 것으로 간주
# 누적 주차 시간이 기본 시간 이하라면, 기본 요금 청구
# 초과하면, 초과한 시간에 대해서 단위 시간마다 단위 요금을 청구한다.
# 초과한 시간이 단위 시간으로 나누어 떨어지지 않으면, 올림한다 = [a] = a보다 작지 않은 최소의 정수

# fees = [기본 시간, 기본 요금, 단위 시간, 단위 요금]
# record = [시각 차량번호 내역]
# 시각 = HH:MM 00:00 ~ 23:59

# 주차 요금 배열, 자동차 입/출차 내역을 나타내는 문자열 배열
import math

# 차량 번호가 작은 자동차부터 청구할 주차 요금 배열 만들기
def sort_car_num_pay(total_pay):
    return [value for key, value in sorted(total_pay.items())]

# 요금 기록
def pay_check(fees, total_pay):
    for key, val in total_pay.items():
        if val <= fees[0]: # 기본 시간 이하시
            total_pay[key] = fees[1] # 기본 요금
        else: # 초과시
            total_pay[key] = fees[1] + math.ceil((total_pay[key] - fees[0]) / fees[2]) * fees[3] # 단위 시간마다 추가 요금 부여

    return sort_car_num_pay(total_pay)

def solution(fees, records):
    record_dict = {}
    total_pay = {}

    for record in records:
        time, car_num, in_out = record.split()
        hour, minutes = map(int, time.split(':'))

        cal_time = hour * 60 + minutes

        if in_out == "IN":
            record_dict[car_num] = cal_time
        elif in_out == "OUT":
            total_time = cal_time - record_dict[car_num] # 출차 시간 - 입차 시간
            if car_num not in total_pay:
                total_pay[car_num] = 0
            total_pay[car_num] += total_time
            del record_dict[car_num]

    end_day = 23 * 60 + 59

    # 출차 시간이 기록 안된 경우
    for key in record_dict:
        total_time = end_day - record_dict[key] # 23:59 출차 처리
        if key not in total_pay:
            total_pay[key] = 0
        total_pay[key] += total_time # 누적 시간 기록

    print(total_pay)
    return pay_check(fees, total_pay)

테케는 통과하고 계속 런타임 에러나 가서 40점대였는데 마지막 출차 시간 기록 안된 경우 처리를 해주면서 total_pay[key] = 0 이 부분을 total_pay[car_num] = 0으로 잘못 써주고 있어서 그랬다..

  • 🌟 개선한 코드
from collections import defaultdict
import math

def sort_car_num_pay(total_pay):
    return [value for key, value in sorted(total_pay.items())]

def pay_check(fees, total_pay):
    for key, val in total_pay.items():
        if val <= fees[0]:
            total_pay[key] = fees[1]
        else:
            total_pay[key] = fees[1] + math.ceil((total_pay[key] - fees[0]) / fees[2]) * fees[3]

    return sort_car_num_pay(total_pay)

def solution(fees, records):
    record_dict = defaultdict(int) # 입차 기록을 담을 defaultdict
    total_pay = defaultdict(int) # 주차 요금을 계산할 defaultdict

    for record in records:
        time, car_num, in_out = record.split()
        hour, minutes = map(int, time.split(':'))

        cal_time = hour * 60 + minutes

        if in_out == "IN":
            record_dict[car_num] = cal_time
        elif in_out == "OUT":
            total_time = cal_time - record_dict[car_num]  # 주차 시간 계산
            total_pay[car_num] += total_time # 해당 차량의 주차 시간 누적
            del record_dict[car_num] # 출차한 차량의 입차 기록 삭제

    # 출차 기록이 없는 차량에 대해 23:59 출차로 간주하여 처리
    for car_num, in_time in record_dict.items():
        total_time = 1439 - in_time  # 23:59까지의 주차 시간 계산
        total_pay[car_num] += total_time

    return pay_check(fees, total_pay)

다른 분의 코드를 참고하니 defaultdict를 활용하는 걸 봤다. defaultdict를 활용하면 굳이 key가 없을 경우 예외 처리를 안해줘도 되서 코드가 훨 간결해진다. 기본값이 0으로 초기화된 dict를 만들지 않아도 되서 공간 복잡도도 낮아진다.

✏️ defaultdict
생성자에 주어진 함수를 사용하여 딕셔너리를 초기화, 이 함수는 딕셔너리에서 키가 발견되지 않을 때마다 호출됨.
일반적인 dict는 해당 키가 없으면 KeyError를 발생시킨다.

시간 복잡도 O(n)
n = len(records)

참고하면 좋은 사이트

dictionary
defaultdict
https://www.geeksforgeeks.org/defaultdict-in-python/

profile
기존 블로그: https://hi-rachel.tistory.com

1개의 댓글

comment-user-thumbnail
2024년 4월 26일

안녕하세요, 99클럽 그룹 리더 조커입니다!
defaultdict를 활용한 풀이 잘 봤습니다
KeyError를 발생 시키지 않는 방법으로 딕셔너리를 참고할 때 get() 메소드를 활용하는 방법도 있습니다!

앞으로도 힘내서 매일 TIL 도전해 보세요! 화이팅입니다 :)
99클럽 https://bit.ly/3TN5TBL

답글 달기