문제: 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
'프로그래머스' 카테고리의 다른 글
[프로그래머스/Python] Lv.2 피로도 (0) | 2024.08.20 |
---|---|
[프로그래머스/Python] 달리기 경주 (0) | 2024.08.13 |
[프로그래머스/python] 뒤에 있는 큰 수 찾기 (0) | 2024.05.31 |
[프로그래머스/python] 2023 KAKAO BLIND RECRUITMENT개인정보 수집 유효기간 (0) | 2024.05.31 |
[프로그래머스/python] 2024 KAKAO WINTER INTERNSHIP가장 많이 받은 선물 (0) | 2024.05.28 |