문제
https://school.programmers.co.kr/learn/courses/30/lessons/92341
사용 언어
Python3
풀이 과정
모각코 문제였는데 오늘은 참가하지 못해 나는 밤에 따로 풀었다.
시간 계산 때문에 예상한 시간을 살짝 넘겨서 풀었는데 점수를 1점밖에 안줘서 당황했다..?!
이유는 예상하긴 했지만 시간 복잡도가 극악이었다..! 지금까지 내 힘으로 푼 것중에 제일 별로라고 할 수 있을 정도. 아예 못풀었음 못풀었지 이건.... 한 번에 통과한 게 신기하네.
시간 날 때 코드 개선하며 어디에서 저렇게 시간을 많이 잡아먹었는지 이유를 알아내야겠다.
아무래도 처음 써 본 datetime 때문인 것 같긴 한데..^_^
제출 답안
# 차량번호 별 머무른 시간 구하기
# fees에 의거하여 요금 구하기
# 차량번호가 작은 순으로 return
import datetime
import math
def solution(fees, records):
answer = []
car_in_record = {}
car_stay_time = {}
remains = []
# 자동차별 머문 시간 계산
for record in records:
time, car, status = record.split()
time = datetime.datetime.strptime(time, "%H:%M")
if status == "IN":
car_in_record[car] = time
remains.append(car)
else:
stay = time - car_in_record[car]
if car not in car_stay_time:
car_stay_time[car] = stay
else:
car_stay_time[car] += stay
remains.remove(car)
# OUT 없이 남아있는 차들 처리
for car in remains:
stay = datetime.datetime.strptime("23:59", "%H:%M") - car_in_record[car]
if car not in car_stay_time:
car_stay_time[car] = stay
else:
car_stay_time[car] += stay
# 주차 요금 계산
charge = []
cars = sorted(list(car_stay_time.keys()))
for car in cars:
stay = car_stay_time[car]
total_minutes = divmod(stay.seconds, 60)[0]
# 기본 시간 이하라면
if total_minutes <= fees[0]:
charge.append(fees[1])
# 기본 시간 초과하면
else:
exceed = fees[1] + math.ceil(((total_minutes - fees[0])/fees[2])) * fees[3]
charge.append(exceed)
return charge
공부한 내용
datetime
아무리 생각해도 효율적인 라이브러리인 것 같진 않지만 그래도 새로 알았으니까...
파이썬에서 날짜, 시간을 다루기 위해서는 datetime이라는 라이브러리를 사용할 수 있다.
import datetime
나는 이번에 datetime, timedelta 두 가지 모듈의 메소드들을 사용해보았다.
# 문자열을 시간 객체로 변환
const str_to_time = datetime.datetime.strptime(date, "%Y-%m-%d")
시간 객체를 원하는 형식의 문자열로 변환하는 메소드는 strftime이다.
참고 : https://ponyozzang.tistory.com/626
datetime 객체끼리 계산하면 자동으로 timedelta(단위 seconds) 객체가 된다.
seconds 값에 접근하여 원하는 값으로 변환하기 위해서는 다음과 같이 사용한다.
time1 = datetime.datetime.strptime("12:25", "%h:%m")
time2 = datetime.datetime.strptime("10:40", "%h:%m")
diff = time1 - time2 # timedelta 객체(초단위)
# 초를 분으로 변환
minutes = divmod(time.seconds, 60)[0]
다른 사람 풀이
1.
나는 이렇게 직접 시간을 계산하기 싫어서 datetime을 찾아봐가며 오히려 시간복잡도가 늘어났는데, 바로 split(':') 해서 계산한 코드 보니 세상 간단해보인다....ㅎㅎ...
편하게 라이브러리 쓰려다가 한참을 돌아가고 좋은 것도 아니었던;; 라이브러리 너무 좋아하는거 반성하자.
import math
def solution(fees, records):
check = {}
for record in records:
time, number, status = record.split()
time = time.split(':')
time = int(time[0])*60 + int(time[1])
if number not in check:
check[number] = (0, time, status)
if status == 'IN':
check[number] = (check[number][0], time, status)
elif status == 'OUT':
total_time, in_time, _ = check[number]
total_time += time - in_time
check[number] = (total_time, time, status)
result = {}
for number in check.keys():
total_time, time, status = check[number]
if status == 'IN':
total_time += 1439 - time
fee = fees[1]
if total_time <= fees[0]:
result[number] = fee
else:
fee = fee + math.ceil((total_time - fees[0]) / fees[2]) * fees[-1]
result[number] = fee
return list(map(lambda x : x[1], sorted(result.items())))
코드를 돌려봤더니 역시 내 코드가 효율성이 극악이었던 거였다..ㅎㅎ 다른 문제와 비슷하게 평균 0초대가 나오더라.
2.
클래스를 이용한 멋진 풀이..!
그리고 출차한 기록이 없는 경우에 out을 직접 넣어줄 생각을 한 게 신기했다.
from collections import defaultdict
from math import ceil
class Parking:
def __init__(self, fees):
self.fees = fees
self.in_flag = False
self.in_time = 0
self.total = 0
def update(self, t, inout):
self.in_flag = True if inout=='IN' else False
if self.in_flag: self.in_time = str2int(t)
else: self.total += (str2int(t)-self.in_time)
def calc_fee(self):
if self.in_flag: self.update('23:59', 'out')
add_t = self.total - self.fees[0]
return self.fees[1] + ceil(add_t/self.fees[2]) * self.fees[3] if add_t >= 0 else self.fees[1]
def str2int(string):
return int(string[:2])*60 + int(string[3:])
def solution(fees, records):
recordsDict = defaultdict(lambda:Parking(fees))
for rcd in records:
t, car, inout = rcd.split()
recordsDict[car].update(t, inout)
return [v.calc_fee() for k, v in sorted(recordsDict.items())]
'코딩 테스트 스터디 > 프로그래머스' 카테고리의 다른 글
[level 2] 튜플 (0) | 2022.09.29 |
---|---|
[level 2] 양궁대회 (0) | 2022.08.10 |
[level 1] 비밀지도 (0) | 2022.07.26 |
[level 3] N으로 표현 (0) | 2022.07.24 |
[level 3] 네트워크 (0) | 2022.07.23 |