[Programmers] 디스크 컨트롤러

Updated:

문제링크


문제 해설

프로세스의 작업 요청 시점과 작업 소요 시간이 주어졌을 때, 요청부터 작업 종료까지의 시간을 최소로 하도록 실행해주는 알고리즘을 설계하는 문제이다.

실행 할 수 있는(작업 시점 기준 혹은 이전에 요청된 프로세스) 프로세스 중 작업 소요 시간이 가장 짧은 프로세스부터 처리하는게 핵심이다. 주의할 점은 작업 요청이 오지도 않았는데 소요 시간이 짧다고 먼저 처리하면 안된다.

answer = 0
time = 0
ps_list = sorted(jobs, key=lambda x : (x[0], x[1]))
waiting_ps = PriorityQueue()

현재 작업 시점을 표현하기 위해 “time” 변수를 선언했다. 그 후 실행 예정 프로세스 리스트(첫 번째 인자)를 작업 요청 시간 기준 오름차순 정렬 후 작업 소요 시간 기준 오름차순 정렬 하였다. 이렇게 하면 리스트의 앞으로 갈 수록 작업이 일찍 요청된, 소요 시간이 짧은 프로세스가 정렬되어 있다.

또 “waiting_ps” 라는 priority queue를 선언했는데, 이는 작업이 요청 되었지만 우선순위가 밀려 실행 대기 중인 프로세스 리스트이다.

waiting_ps에 데이터를 넣을 땐 [소요 시간, 요청 시간] 꼴로 넣는다. queue에 들어있는 프로세스들은 모두 실행 요청된 상태이므로 작업 소요 시간이 짧은 순으로 실행되면 되기 때문에 소요 시간을 key로 두기 위해 순서를 바꾸어 넣는다.

while len(ps_list) > 0 or not waiting_ps.empty():
    if waiting_ps.empty():
        ps = ps_list.pop(0)
        time = ps[0] + ps[1]
    else:
        ps = waiting_ps.get()
        ps = (ps[1], ps[0])
        time += ps[1]
    answer += time - ps[0]
    while len(ps_list) > 0:
        if time > ps_list[0][0]:
            tmp = ps_list.pop(0)
            waiting_ps.put((tmp[1], tmp[0]))
        else:
            break

프로세스 리스트인 ps_list와 대기 리스트인 waiting_ps가 모두 비어 있으면 더 이상 실행할 프로세스가 없기 때문에 while문의 조건을 위와 같이 설정한다.

만약 waiting_ps가 비어있다면, 실행 대기 중인 프로세스가 없다는 의미이므로 ps_list에서 요청 예정인 프로세스를 바로 실행한다. 해당 프로세스는 대기 없이 요청 시점에 바로 실행되기 때문에 실행 시간 및 종료 시간은 (작업 요청 시점)과 (작업 요청 시점 + 작업 소요 시간)이 된다. time의 값을 새로 업데이트 한다.

만약 waiting_ps에 대기 중인 프로세스가 있다면 우선순위가 높은 프로세스를 뽑아서 실행한다.

실행한 프로세스의 요청 시점 ~ 종료 시점은 작업 종료 시점인 time - 작업 요청 시점인 ps[0]을 빼서 구해준다. 그 값을 answer에 더해준다.

그 후, 새로 업데이트된 작업 시점 time에 대해, ps_list에서 time과 같은, 혹은 이전에 작업 요청된 프로세스가 있는지 확인한다. 있다면 waiting_ps에 넣는다.

위 반복문이 모두 종료되면 answer에는 모든 프로세스의 작업 요청 시점 ~ 종료 시점까지의 소요 시간의 합이 저장되어 있을 것이다. 따라서 이를 프로세스의 수로 나누어(소수점 버림 처리) return 해준다.

전체 코드는 아래와 같다.

python 코드


from queue import PriorityQueue
def solution(jobs):
    answer = 0
    time = 0
    ps_list = sorted(jobs, key=lambda x : (x[0], x[1]))
    waiting_ps = PriorityQueue()

    while len(ps_list) > 0 or not waiting_ps.empty():
        if waiting_ps.empty():
            ps = ps_list.pop(0)
            time = ps[0] + ps[1]
        else:
            ps = waiting_ps.get()
            ps = (ps[1], ps[0])
            time += ps[1]

        answer += time - ps[0]
        print("time : " + str(time) + "  (" + str(ps[0]) + "," + str(ps[1]) + ")")

        while len(ps_list) > 0:
            if time > ps_list[0][0]:
                tmp = ps_list.pop(0)
                waiting_ps.put((tmp[1], tmp[0]))
            else:
                break

    return answer//len(jobs)
    

Leave a comment