규도자 개발 블로그

[프로그래머스/Level2/파이썬3(python3)] 프린터 본문

알고리즘/풀이

[프로그래머스/Level2/파이썬3(python3)] 프린터

규도자 (gyudoza) 2020. 5. 11. 12:43

[프로그래머스/Level2/파이썬3(python3)] 프린터

문제

일반적인 프린터는 인쇄 요청이 들어온 순서대로 인쇄합니다. 그렇기 때문에 중요한 문서가 나중에 인쇄될 수 있습니다. 이런 문제를 보완하기 위해 중요도가 높은 문서를 먼저 인쇄하는 프린터를 개발했습니다. 이 새롭게 개발한 프린터는 아래와 같은 방식으로 인쇄 작업을 수행합니다.

1. 인쇄 대기목록의 가장 앞에 있는 문서(J)를 대기목록에서 꺼냅니다.
2. 나머지 인쇄 대기목록에서 J보다 중요도가 높은 문서가 한 개라도 존재하면 J를 대기목록의 가장 마지막에 넣습니다.
3. 그렇지 않으면 J를 인쇄합니다.

예를 들어, 4개의 문서(A, B, C, D)가 순서대로 인쇄 대기목록에 있고 중요도가 2 1 3 2 라면 C D A B 순으로 인쇄하게 됩니다.

내가 인쇄를 요청한 문서가 몇 번째로 인쇄되는지 알고 싶습니다. 위의 예에서 C는 1번째로, A는 3번째로 인쇄됩니다.

현재 대기목록에 있는 문서의 중요도가 순서대로 담긴 배열 priorities와 내가 인쇄를 요청한 문서가 현재 대기목록의 어떤 위치에 있는지를 알려주는 location이 매개변수로 주어질 때, 내가 인쇄를 요청한 문서가 몇 번째로 인쇄되는지 return 하도록 solution 함수를 작성해주세요.

제한사항

  • 현재 대기목록에는 1개 이상 100개 이하의 문서가 있습니다.
  • 인쇄 작업의 중요도는 1~9로 표현하며 숫자가 클수록 중요하다는 뜻입니다.
  • location은 0 이상 (현재 대기목록에 있는 작업 수 - 1) 이하의 값을 가지며 대기목록의 가장 앞에 있으면 0, 두 번째에 있으면 1로 표현합니다.

입출력 예

prioritieslocationreturn
[2, 1, 3, 2]21
[1, 1, 9, 1, 1, 1]05

입출력 예 설명

예제 #1

문제에 나온 예와 같습니다.

예제 #2

6개의 문서(A, B, C, D, E, F)가 인쇄 대기목록에 있고 중요도가 1 1 9 1 1 1 이므로 C D E F A B 순으로 인쇄합니다.

풀이

def solution(priorities, location):
    answer = 0
    max_priority = max(priorities)
    while True:
        current_priority = priorities.pop(0)
        if max_priority == current_priority:
            answer += 1
            if location == 0:
                break
            else:
                location -= 1
            max_priority = max(priorities)
        else:
            priorities.append(current_priority)
            if location == 0:
                location = len(priorities) - 1
            else:
                location -= 1
    return answer

설명

꽤나 애를 먹었던 문제이다. 몇번이고 풀어보다가 우수수수 떨어지는 불일치 판정에 넋을 잃고 다른 사람들이 올려놓은 코드를 분석하는 식으로 공부하였다. 이것 또한 가장 흔하게 발견되는 코드를 그냥 나 나름대로 변수를 파악하기 쉽게 변경한 것이다.
 나는 맨 처음 문제를 풀었을 때 index와 priorities가 담긴 딕셔너리를 만들고, 그 딕셔너리를 이 문제에서 요구하는 대로 각 원소의 뒤에 자신보다 큰 priority가 있으면 맨 뒤로 이동시키는 식으로 딕셔너리를 전부 정렬시킨 다음에 요구받은 location에 있던 아이가 정렬이 끝난 뒤 몇번째에 위치하고 있는지 return하는 식으로 만들었는데 왠지 모르게 특정 케이스에서 실패가 계속 뜨는 것이다. 도무지 해결할 수 있는 방법이 떠오르지 않는 나는 역시나 구글링을 했고 찾아낸 코드가 저 코드이다.
 이 코드는 내가 생각한 것과는 달리 따로 list나 dict의 선언이 따로 없어 메모리를 절약할 수 있다. 방법도 기발하고 깔끔하다. 실제 문제에서 묘사된 프린터기의 작동과 유사하다고 볼 수 있다.
 일단 저 while문을 빠져나갈 수 있는 조건문은 단 한곳 뿐이라는 것에 주목하면 편하다. 그곳이 바로 언제이냐, 현재 걸려있는 인쇄물이 가장 우선도가 높으면서 그것이 location으로 지정했던 문서일 때이다. 그러니까 이 함수는 location 매개변수로 지정했던 위치의 문서가 인쇄될 때 끝난다. 각 if문의 흐름을 보면 현재 인쇄 대기중인 문서가 priority가 제일 높지 않으면 큐의 맨 뒤로 보내고 모든 문서목록은 앞으로 당겨(location -= 1) location의 위치를 잃지 않고, 혹은 priority가 제일 높아 인쇄가 되더라도 location으로 지정했던 문서가 아니라면 걸려있던 문서를 인쇄하여 맨 앞에 있던 큐를 없애고 나머지 문서들을 앞으로 당겨(location -= 1) location의 위치를 잃지 않는다. 만약에 지정했던 문서인데 우선순위가 높은 다른 문서가 있으면 맨 뒤로 옮기고 location을 초기화(location = len(priorities) - 1)한다.
 프린터의 동작의 네가지 분기를 정확하고 간단하게 구현해낸 코드인 것 같다. 많이배웠다.



Comments