[프로그래머스 LV.2 과제 진행하기]
문제 링크: https://school.programmers.co.kr/learn/courses/30/lessons/176962
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
<문제>
문제 설명
과제를 받은 루는 다음과 같은 순서대로 과제를 하려고 계획을 세웠습니다.
- 과제는 시작하기로 한 시각이 되면 시작합니다.
- 새로운 과제를 시작할 시각이 되었을 때, 기존에 진행 중이던 과제가 있다면 진행 중이던 과제를 멈추고 새로운 과제를 시작합니다.
- 진행중이던 과제를 끝냈을 때, 잠시 멈춘 과제가 있다면, 멈춰둔 과제를 이어서 진행합니다.
- 만약, 과제를 끝낸 시각에 새로 시작해야 되는 과제와 잠시 멈춰둔 과제가 모두 있다면, 새로 시작해야 하는 과제부터 진행합니다.
- 멈춰둔 과제가 여러 개일 경우, 가장 최근에 멈춘 과제부터 시작합니다.
과제 계획을 담은 이차원 문자열 배열 plans가 매개변수로 주어질 때, 과제를 끝낸 순서대로 이름을 배열에 담아 return 하는 solution 함수를 완성해주세요.
제한사항
- 3 ≤ plans의 길이 ≤ 1,000
- plans의 원소는 [name, start, playtime]의 구조로 이루어져 있습니다.
- name : 과제의 이름을 의미합니다.
- 2 ≤ name의 길이 ≤ 10
- name은 알파벳 소문자로만 이루어져 있습니다.
- name이 중복되는 원소는 없습니다.
- start : 과제의 시작 시각을 나타냅니다.
- "hh:mm"의 형태로 "00:00" ~ "23:59" 사이의 시간값만 들어가 있습니다.
- 모든 과제의 시작 시각은 달라서 겹칠 일이 없습니다.
- 과제는 "00:00" ... "23:59" 순으로 시작하면 됩니다. 즉, 시와 분의 값이 작을수록 더 빨리 시작한 과제입니다.
- playtime : 과제를 마치는데 걸리는 시간을 의미하며, 단위는 분입니다.
- 1 ≤ playtime ≤ 100
- playtime은 0으로 시작하지 않습니다.
- 배열은 시간순으로 정렬되어 있지 않을 수 있습니다.
- name : 과제의 이름을 의미합니다.
- plans의 원소는 [name, start, playtime]의 구조로 이루어져 있습니다.
- 진행중이던 과제가 끝나는 시각과 새로운 과제를 시작해야하는 시각이 같은 경우 진행중이던 과제는 끝난 것으로 판단합니다.
<문제 풀이>
우선, 주어진 plans 배열의 시간 단위를 분으로 통일하기로 했다. start의 시간 부분에 60을 곱해 분과 더해 하나로 만들어 주었다.
그 뒤, 시작 시간을 기준으로 정렬하였다.
첫 번째 인덱스의 값을 기준으로 선언하고 반복문을 시작했다.
시작 시간과 이전 시작 시간의 차이만큼이 사용할 수 있는 시간이라 생각했고, tmp 배열에 저장한 값들을 하나씩 꺼내 가며 playtime 부분을 줄여나갔다.
도중, playtime이 0이 되는 경우는 answer 배열에 추가하고, tmp 배열에서 제거했다. 그 외의 경우 다시 tmp 배열에 남은 playtime과 함께 추가했다.
시간 차이를 모두 사용한 뒤, 기준점을 현재 인덱스의 값으로 변경해 주었다.
반복문을 모두 종료한 뒤, tmp 배열에 남은 내용들 중 과목을, 역순으로 answer 배열에 붙여주면 답이 된다.
<소스코드>
def solution(plans):
answer = []
times = [[sub, int(start.split(":")[0]) * 60 + int(start.split(":")[1]), int(playtime)] for sub, start, playtime in plans]
times.sort(key=lambda x:x[1])
tmp = [(times[0][0], times[0][2])]
pre_start = times[0][1]
for sub, start, playtime in times[1:]:
exchange = start - pre_start
while exchange >= 0 and tmp:
s, pt = tmp.pop(-1)
exchange -= pt
if exchange >= 0:
answer.append(s)
else:
tmp.append((s, -exchange))
tmp.append((sub, playtime))
pre_start = start
answer.extend([i[0] for i in tmp[::-1]])
return answer