전공/프로그래머스

과제 진행하기

yha97 2023. 10. 12. 22:19

날짜 : 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 문을 탈출할 때, 즉 남아있는 시간이 남아있는 과목의 소요시간보다 작은 경우 남은 시간을 전부 사용하지 않고 탈출해서 오답으로 체크되어 있었다.

- 거의 한 줄만 수정하면 되는 거였는데 많은 시간을 투자했고, 그래도 스스로 풀어서 뿌듯하다.

 

 

참고 사이트