Programming/Coding Test

[Coding Test] 2022 KAKAO BLIND RECRUITMENT - 주차 요금 계산

조상현 2022. 9. 26. 16:57

문제해결 프로그래밍 공부를 위해 2022 KAKAO BLIND RECRUITMENT 코딩 테스트 문제 리뷰를 진행하고자 합니다.

 

문제는 https://school.programmers.co.kr/learn/challenges?page=1&partIds=25448 에서 풀어볼 수 있습니다.

 

두번 째로 풀어볼 문제는 58%의 정답률을 보이는 신고 결과 받기입니다.

 

지난번 풀었던 신고 결과 받기보다 레벨은 높은데 정답률은 높은 문제입니다.

 

 

그럼 바로 문제를 풀어보겠습니다.

 

문제 설명은 다음과 같고 요약하자면 요금표와 차량들의 입/출차기록이 주어졌을 때 차량 별로 요금을 계산하는 문제입니다.

 

 

주의할 점은 출차기록이 없는 차에 대해서는 23:59로 출차처리를 해야한다는 점과 동일한 번호판에 대해서 각각의 입/출차가 아니라 모든 시간을 합쳐서 요금을 계산해야한다는 것, 최종 출력은 오름차순으로 이렇게 세가지입니다.

 

그럼 바로 문제를 풀어보겠습니다.

 

def solution(fees, records):
    answer = []

    total_time = dict()
    last_record = dict()

 

차량 별로 마지막 입/출차 기록과 총 주차시간을 계산하기 위해 dict를 선언해줍니다.

 

이후 records를 파싱하여 시각, 차량 번호, 내역을 분리하고 계산편의성을 위해 시각을 초 단위로 변환해줍니다.

 

for rec in records:
    time_hhmm, car_number, status = rec.split(' ')
    
    time_hh, time_mm = time_hhmm.split(':')
    sec = (int(time_hh) * 3600) + (int(time_mm) * 60)

 

if문을 사용해 현재 기록이 입차 기록이라면 마지막 기록에 입력해주고, 출차 기록이라면 출차시간에서 입차시간을 빼서 총 주차시간에 더해줍니다.

 

last_record.pop(car_number)를 이용해 처리가 끝난 기록은 삭제해줍니다.

 

if car_number not in total_time.keys():
    total_time[car_number] = 0
if car_number not in last_record.keys():
    last_record[car_number] = sec
else:
    total_time[car_number] += sec - last_record[car_number]
    last_record.pop(car_number)

 

다음으로 위에 주의사항에 언급한 출차기록이 없는 차량들에 대해서 처리를 합니다.

 

위에서 last_record.pop(car_number)를 이용해 출차기록이 있는 차량들은 처리해줬기 때문에 last_record에는 출차기록이 없는 차량들만 존재합니다.

 

마지막 기록을 돌며 23:59 출차를 기준으로 하여 총 주차시간에 더하여 줍니다.

 

no_out = (23 * 3600) + (59 * 60)
for car_number in last_record.keys():
    total_time[car_number] += no_out - last_record[car_number]

 

이제 sorted 함수를 이용해 오름차순으로 정렬시키고 총 주차시간을 이용해 주차요금을 계산합니다. (이 때 주의할 점은 제공하는 기본 시간과 단위 시간은 분을 기준으로 하기 때문에 총 주차시간을 분으로 변환하여 계산합니다.)

 

for car_number in sorted(total_time.keys()):
    fee = calc_fee(fees, int(total_time[car_number] / 60))
    answer.append(fee)
return fee

 

아래는 요금을 계산하는 calc_fee 함수입니다.

 

def calc_fee(fees, total_time):
    overtime = total_time - fees[0]
    if overtime > 0:
        fee = fees[1] + math.ceil(overtime / fees[2] * fees[3])
        return fee
    else:
        return fees[1]

 

기본 시간을 넘지 않는 경우 기본 요금을 return 시키고 초과분에 대해서는 단위 시간을 이용해 요금을 계산합니다.

 

이 때 주의할 점은 초과분을 계산할 때 단위 시간에 미치지 못하는 나머지 시간도 1단위로 계산한다는 점입니다.

예를 들어 단위 시간이 10분이고, 초과한 시간이 23분이라면 초과 주차요금은 단위 요금 * 3이 되는 것입니다.

 

코드 전문은 다음과 같습니다.

 

def solution(fees, records):
    answer = []
    
    total_time = dict()
    last_record = dict()
    for rec in records:
        time_hhmm, car_number, status = rec.split(' ')

        time_hh, time_mm = time_hhmm.split(':')
        sec = (int(time_hh) * 3600) + (int(time_mm) * 60)
        
        car_number = rec[1]

        if car_number not in total_time.keys():
            total_time[car_number] = 0
        if car_number not in last_record.keys():
            last_record[car_number] = sec
        else:
            total_time[car_number] += sec - last_record[car_number]
            last_record.pop(car_number)
    
    no_out = ((23 * 3600) + (59 * 60))
    for car_number in sorted(last_record.keys()):
        total_time[car_number] += no_out - last_record[car_number]
        
    for car_number in sorted(total_time.keys()):
        fee = calc_fee(fees, int(total_time[car_number] / 60))
        answer.append(fee)
        
    return answer

def calc_fee(fees, total_time):
    overtime = total_time - fees[0]
    if overtime > 0:
        fee = fees[1] + math.ceil(overtime / fees[2] * fees[3])
        return fee
    else:
        return fees[1]

 

다음글에서는 양과 늑대 문제를 풀어보겠습니다.