본문 바로가기
프로그래머스

[프로그래머스/python] 2022 KAKAO BLIND RECRUITMENT 주차 요금 계산

by 보먀 2024. 6. 11.
728x90
반응형

문제: https://school.programmers.co.kr/learn/courses/30/lessons/92341

 

프로그래머스

코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.

programmers.co.kr

 

 

사용 알고리즘: 없음 -> 구현

 

 

주차장의 요금표와 차량의 입출차 기록이 주어졌을 때 하루동안 차 번호별 주차 요금을 계산하는 문제.

차 번호 오름차순 순으로 요금이 얼마인지 계산해서 리턴해줘야 함.

 

아래와 같이 fees 와 records 가 입력으로 주어짐. 

 

 

로직

1. records 를 차 번호를 기준으로 정렬

2. 요금을 쉽게 계산하기 위해 입차 내역과 출차 내역을 분리해서 딕셔너리에 넣어줌 (번호로 뽑아서 쉽게 쓰기 위해 딕셔너리 사용)

3. 차 번호 별로 총 시간과 요금 계산

  • 입차 기록만 있는 경우
  • 입차 + 출차 기록이 모두 있는 경우

 

1. 차 번호를 오름차순으로 정렬

 

입력을 보면 "hh:mm nnnn IN" 형식으로 nnnn 에 차 번호가 들어가 있다. 차 번호로 정렬하기 위해 람다 함수를 사용해서 인덱스 [6:10]을 기준으로 정렬해줌.

records = sorted(records, key=lambda record: record[6:10])

 

 

 

2. 요금 계산을 위해 입출차 내역 기록

 

fees 값은 차례대로 기본시간 / 기본요금 / 단위시간 / 단위시간당 요금이기 때문에 차례대로 해당 변수에 값을 넣어줌.

inRecords, outRecords 딕셔너리를 만들고 각 디셔너리를 입차기록, 출차기록으로 씀.

-> inRecords = {차번호1: [입차시간1, 입차시간2], 차번호2: ...}

-> outRecords = {차번호2: [출차시간1, 출차시간2], 차번호2: ...}

 

for 문을 돌면서 IN / OUT 의 경우를 나눠서 입차/출차 차 번호와 시각을 기록함.

한 차가 하루에 여러 번 들어왔다가 나갈 수 있으므로 입출차 기록이 여러 개일 수 있기 때문에 딕셔너리의 value 값이 리스트여야 함!

-> 딕셔너리에 처음 들어오는 차 번호일 때 먼저 리스트로 value 값을 초기화하고 append 를 사용해 값을 넣어줌

 

# 시간, 요금
basicTime = fees[0]
basicFee = fees[1]
excessTime = fees[2]
excessFee = fees[3]

# in, out
inRecords = {}
outRecords = {}

# 딕셔너리에 넣기
for i in range(len(records)):
    time, num, inout = records[i].split()

    if inout == "IN":
        if inRecords.get(num) is None:
            inRecords[num] = []
        inRecords[num].append(time)
    else:
        if outRecords.get(num) is None:
            outRecords[num] = []
        outRecords[num].append(time)

 

 

 

3. 요금 계산

 

- 입차 기록만 있는 경우

 

입차기록만 있다 == 출차기록이 없다 이기 때문에 if 문의 조건을 아래와 같이 걸어서 필터링 해주고 총 시간을 분으로 바꾸어 계산해줌

# 요금 계산
for i, (num, inoutList) in enumerate(inRecords.items()):
    totalFees = 0
    totalTime = 0
    
    # 입차 기록만 있는 경우
    if outRecords.get(num) is None:
        inH, inM = inRecords[num][0].split(":")
        inH = int(inH)
        inM = int(inM)

        totalTime += (23-inH) * 60 + (59-inM)

 

 

- 입차 기록, 출차 기록 모두 있는 경우

 

어떤 차 번호를 가진 차의 입출차 기록을 봤을 때 첫번째 경우는 가능하지만 두번째 경우는 불가능하다. 이미 있는 차 번호가 또 입차하는 것이 불가능하기 때문이다. 그래서 마지막에 들어온 입차 기록만 찍히고 언제 나갔는지 출차 기록이 안된 경우만 고려해주면 된다. 

- 입차 출차 입차 (o)

- 입차 입차 출차 (x)

 

for 문을 돌면서 입차 출차 기록을 이용해 총 시간을 구해 분으로 바꾸고, 차의 마지막 기록이 입차 기록만 존재하고 끝날 경우를 23:59분에 출차 되었다고 가정하고 이용시간을 구해 총 시간에 더해주면 된다. 

 

마지막 기록이 입차기록인 경우, 출차기록보다 입차기록이 1개 더 존재하기 때문에 len(outRecords[num]) < len(inRecords[num]) 으로 필터링해서 걸러주면 된다. 

# 입출차 기록이 모두 있는 경우
else:
    for j in range(len(outRecords[num])):
        inH, inM = inRecords[num][j].split(":")
        outH, outM = outRecords[num][j].split(":")
        
        # int 형으로 변환
        inH = int(inH)
        inM = int(inM)
        outH = int(outH)
        outM = int(outM)

        totalTime += (outH-inH) * 60 + (outM-inM)
	
    # 차가 마지막으로 입차하고 몇 시에 나간지 출차 기록이 안된 경우
    if len(outRecords[num]) < len(inRecords[num]):
        inH, inM = inRecords[num][-1].split(":")
        
        # int 형으로 변환
        inH = int(inH)
        inM = int(inM)
        
        totalTime += (23-inH) * 60 + (59-inM)

 

 

- 요금 계산

  • 총 시간이 기본 시간보다 적은 경우 -> 5000
  • 총 시간이 기본 시간보다 많은 경우 -> 초과 요금을 계산해서 더해줘야 함
if totalTime <= basicTime:
    totalFees = basicFee
else:
    totalFees = basicFee + (ceil((totalTime-basicTime)/excessTime) * excessFee)
    
answer.append(totalFees)

 

 

 

전체 코드

from math import ceil

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

    # 차번호 오름차순으로 정렬
    records = sorted(records, key=lambda record: record[6:10])

    # 시간, 요금
    basicTime = fees[0]
    basicFee = fees[1]
    excessTime = fees[2]
    excessFee = fees[3]

    # in, out
    inRecords = {}
    outRecords = {}

    # 딕셔너리에 넣기
    for i in range(len(records)):
        time, num, inout = records[i].split()

        if inout == "IN":
            if inRecords.get(num) is None:
                inRecords[num] = []
            inRecords[num].append(time)
        else:
            if outRecords.get(num) is None:
                outRecords[num] = []
            outRecords[num].append(time)
   
   # 요금 계산
    for i, (num, inoutList) in enumerate(inRecords.items()):
        totalFees = 0
        totalTime = 0
        # 입차 기록만 있는 경우
        if outRecords.get(num) is None:
            inH, inM = inRecords[num][0].split(":")
            
            # int 형으로 변환
            inH = int(inH)
            inM = int(inM)

            totalTime += (23-inH) * 60 + (59-inM)
            
        # 입출차 기록이 모두 있는 경우
        else:
            for j in range(len(outRecords[num])):
                inH, inM = inRecords[num][j].split(":")
                outH, outM = outRecords[num][j].split(":")
                
                # int 형으로 변환
                inH = int(inH)
                inM = int(inM)
                outH = int(outH)
                outM = int(outM)

                totalTime += (outH-inH) * 60 + (outM-inM)

            if len(outRecords[num]) < len(inRecords[num]):
                inH, inM = inRecords[num][-1].split(":")
                
                # int 형으로 변환
                inH = int(inH)
                inM = int(inM)
                
                totalTime += (23-inH) * 60 + (59-inM)
		
        # 요금 계산
        if totalTime <= basicTime:
            totalFees = basicFee
        else:
            totalFees = basicFee + (ceil((totalTime-basicTime)/excessTime) * excessFee)
        answer.append(totalFees)
    return answer
728x90
반응형