과제 진행하기
날짜 : 2023. 10. 12
사용 언어 : python
문제
코드
def solution(plans):
def time_cal(a, b): # b와 a 시간계산(분)
hour = (b[0] - a[0])
minute = (b[1] - a[1])
if minute < 0:
hour -= 1
minute += 60
return hour * 60 + minute
res = list()
arr = list()
for sub, time, cost in plans: # 전처리
h, m = time.split(":")
arr.append([sub, int(h), int(m), int(cost)])
arr.sort(key = lambda x : (x[1], x[2])) # 시간 순으로 정렬
rest = list() # 남아있는 과목 수
rest.append(arr[0])
now_h, now_m = arr[0][1], arr[0][2] # 현재 시, 분
for i in range(1, len(plans)):
h, m = arr[i][1], arr[i][2]
left = time_cal([now_h, now_m], [h, m]) # 다음 과목까지의 시간
now_h, now_m = h, m # 시간 최신화
if left < rest[-1][3]: # 못끝냄
rest[-1][3] -= left
elif left == rest[-1][3]:
res.append(rest.pop()[0]) # 결과 삽입
else: # 끝낼 수 있음
left -= rest[-1][3] # 남아있는 시간 갱신
res.append(rest.pop()[0]) # 결과 삽입
while rest:
if left >= rest[-1][3]: # 추가로 과제 완료
left = left - rest[-1][3] # 남아있는 시간 갱신
res.append(rest.pop()[0]) # 결과 삽입
else:
rest[-1][3] -= left # 추가 과제 남기는 경우(new 과제 시작)
break
rest.append(arr[i])
while rest: res.append(rest.pop()[0])
return res
풀이
- 시작 시간, 소요시간이 int형 변수가 아니기 때문에 각 타입에 맞게 전처리 후 다시 리스트를 구성한 다음, 시간 순서에 맞게 정렬한다.
- 이후 시간을 계산할 함수를 만들고, 스택에 맨 처음 과목에 대한 정보를 넣고 그 다음 원소에 대해서 for문을 돌린다.
- 해당 시간까지 앞선 과제를 끝낼 수 없는 경우, 하나만 제대로 끝내는 경우, 그 이상으로 끝내는 경우 이 3가지 케이스로 나누어 전개한다.
- 과제를 끝낼 수 없는 경우에는 그 시간까지 투자한 시간을 해당 과목에 반영한다.
- 그 시간까지 투자한 시간과 과목의 소요시간이 동일한 경우에는 스택에서 과목을 pop 하고, 그 과목의 명칭을 결과 리스트에 삽입한다.
- 마지막으로 1개를 끝내고 시간이 남은 경우에는 while문을 통해 추가로 과제를 완료했는지 여부를 체크하고, 각 시간을 갱신하면서 반복한다.
- 다만, 남아있는 시간이 남아있는 과목의 소요시간보다 작은 경우 해당 시간에 대해 과목의 소요시간에 반영한 다음 반복문을 탈출한다.
- 그리고 스택의 가장 윗부분에 해당 시간의 새로운 과목을 추가하여 우선순위를 높여준다.
- 전체 for문을 실행한 다음 스택에 남아있는 값들에 대해 역순으로 pop 하면서 결과 리스트에 과목 명칭들을 삽입한 다음 해당 리스트를 리턴한다.
알게된 점
- 문제 방향은 곧바로 잡았지만 마지막에 테스트케이스 4, 5, 6, 10에서 계속 막혔다.
- 2시간 가량 머리를 싸매고 풀이한 결과, while 문을 탈출할 때, 즉 남아있는 시간이 남아있는 과목의 소요시간보다 작은 경우 남은 시간을 전부 사용하지 않고 탈출해서 오답으로 체크되어 있었다.
- 거의 한 줄만 수정하면 되는 거였는데 많은 시간을 투자했고, 그래도 스스로 풀어서 뿌듯하다.
참고 사이트
-