LV2 연습문제를 풀어보았다.
https://school.programmers.co.kr/learn/courses/30/lessons/176962
문제의 핵심조건은
1. 다음과제 시작시간까지 현재과제가 미완료되면 미루고 다음과제를 시작한다.
2. 다음과제 시작시간까지 현재과제가 완료되면 최근 미뤄둔 과제부터 한다.->스택 사용
+시간계산이 필요함(문제에선 HH:MM으로 주어졌지만 분 단위로 바꿔서 하는 게 더 편리했다.)
단순하게 시간비교를 하면서 스택을 이용한 구현으로 갔다. 함수로 정리한다고는 했지만 좀 길다.
def calculMinute(string):
hour, min = map(int, string.split(':'))
time = hour * 60 + min
return time
def pushInStack(limit_time, play_time,name,stack, answer, real_time):
if(limit_time < play_time):
new_time = play_time - limit_time
stack.append((name, new_time))
real_time += limit_time #제한시간까지만 채워짐
elif(limit_time > play_time):
answer.append(name)
real_time += play_time# 수행한 만큼만 시간이 감
elif(limit_time == play_time):
answer.append(name)
real_time += play_time# 수행한 만큼만 시간이 감
return real_time
def solution(plans):
answer = []
stack = []
plans.sort(key=lambda x:x[1])
real_time = calculMinute(plans[0][1]) #현재시간 초기화
for i in range(len(plans)-1):
name,cur_time, need_time = plans[i][0], calculMinute(plans[i][1]), int(plans[i][2])
next_time = calculMinute(plans[i+1][1]) #다음과제 시작시간
limit_time = next_time - cur_time
real_time = cur_time
#다음 과제 시작시간까지 현재 과제를 못 마칠 것으로 예상됨
if(limit_time < need_time):
real_time = pushInStack(limit_time, need_time, name, stack, answer, real_time)
#꽉 채워서 현재 과제를 수행할 것으로 예상됨
elif(limit_time == need_time):
real_time = pushInStack(limit_time, need_time, name, stack, answer, real_time)
#현재 과제를 해도 시간이 남을 것으로 예상됨
elif(limit_time > need_time):
real_time = pushInStack(limit_time, need_time, name, stack, answer, real_time)
while stack:
name, time = stack.pop()
updated_limit = (next_time-real_time)
#여분과제 제한시간이 남은 시간보다 커서 다 못마칠 경우
if(time > updated_limit):
real_time = pushInStack(updated_limit, time, name, stack, answer, real_time)
#다음 과제로 넘어가기
break
#시간이 딱 맞을 경우
elif(time == updated_limit):
real_time = pushInStack(updated_limit, time, name, stack, answer, real_time)
#다음과제로 넘어가기
break
#또다른 여분 과제를 할 수 있을 경우
elif(time < updated_limit):
real_time = pushInStack(updated_limit, time, name, stack, answer, real_time)
#마지막 과제는 무조건 수행완료됨
answer.append(plans[-1][0])
while stack:
name, time = stack.pop()
answer.append(name)
return answer
다른 사람의 풀이를 보고 선정했다. 주관적이지만 더 좋은 코드라고 생각한다.
핵심 아이디어는 해당 과제가 '언제 끝날지'이다. 따라서 언제 끝날지 시간갱신을 한 다음에, sort()함수로 완료순으로 답을 도출한다.
1.정렬 및 시간 전처리를 한 [["music", "740", "40"], ["computer", "750", "100"],["science", "760", "50"], ["history", "840", "30"]] 이 상태에서 과제의 완료시간을 계산한다. 그 다음 과제의 시작시간과 비교했을 때 그 시간을 넘어간다면 미뤄지고, 넘어가지 않으면 미뤄지지 않는다.
2.미뤄질 경우, 새로 시작하는 과제의 수행시간만큼 미뤄질 것이므로 미뤄지는 과제의 완료시간은 더 늘어난다.
3.반면 미뤄지지 않는 경우 과제를 완수했다는 뜻이므로 과제의 완료시간은 더 이상 갱신되지 않는다.
4.과제의 완료시간을 기준으로 lst를 sort 하면, 간단하게 해결된다.
***주의할 게 시간을 더한다고 해서 과제의 완료시간은 정확하게 계산되지 않는다. 대충 미뤄지냐, 안 미뤄지냐를 판단하기 위한 상대적인 값이다. (이런 점이 생각하기 힘든 아이디어 였다.)
def solution(plans):
plans = sorted(map(lambda x: [x[0], int(x[1][:2]) * 60 + int(x[1][3:]), int(x[2])], plans), key=lambda x: -x[1])
lst = []
while plans:
x = plans.pop()
for i, v in enumerate(lst):
if v[0] > x[1]:
lst[i][0] += x[2]
lst.append([x[1] + x[2], x[0]])
lst.sort()
return list(map(lambda x: x[1], lst))