STUDY/알고리즘

[프로그래머스] 프린터 (Python)

seonyounggg 2021. 2. 18. 23:47

✏️ 문제

 

코딩테스트 연습 - 프린터

일반적인 프린터는 인쇄 요청이 들어온 순서대로 인쇄합니다. 그렇기 때문에 중요한 문서가 나중에 인쇄될 수 있습니다. 이런 문제를 보완하기 위해 중요도가 높은 문서를 먼저 인쇄하는 프린

programmers.co.kr

✏️ 풀이

priorities배열에는 같은 원소도 존재하기 때문에 고유한 인덱스를 따로 저장할 공간이 필요하다.

그 후 인덱스 배열과 우선순위 배열을 동일하게 이동해야 한다.

반복문을 돌면서, head가 가장 큰 우선순위를 가지면 해당 원소를 프린트 해준다. (del, pop)

이 때 프린트 회수를 1 증가 시켜준다. (while문 돌 때마다 증가하는 거 아님 주의! 그냥 뒤로 보내는 건 출력하는 횟수에 포함되지 않는다.)

출력되는 원소가 원하는 위치의 원소일 경우 즉시 정답을 반환해주었다.

head보다 큰 우선순위가 존재한다면 head를 tail로 보내준다.

어려워보였지만 인덱스를 따로 저장한다는 아이디어를 생각한 이후로는 꽤 쉽게 풀렸다.

✏️ 코드

def solution(priorities, location):
    count = 0    
    idx = [i for i in range(len(priorities))]

    if len(priorities) == 0:
        return 1
        
    while len(priorities) > 0:
        if priorities[0] >= max(priorities):
            count += 1
            if idx[0] == location:
                return count
            del priorities[0]
            del idx[0]
        else:
            priorities = priorities[1:] + [priorities[0]]
            idx = idx[1:] + [idx[0]]
    
    return count

✏️ 다른 사람 풀이

 def solution(priorities, location):
    queue =  [(i,p) for i,p in enumerate(priorities)]
    answer = 0
    while True:
        cur = queue.pop(0)
        if any(cur[1] < q[1] for q in queue):
            queue.append(cur)
        else:
            answer += 1
            if cur[0] == location:
                return answer

인덱스를 저장하기 위한 리스트를 따로 두는 대신 튜플을 활용하였다.

아무래도 리스트를 따로 두면 실수의 가능성이 높아져서 이 방식이 훨씬 좋아보인다.

( any함수에 대해 처음 알게되었다.

iterable한 타입을 넣으면 그 중에 하나라도 조건이 True라면 True를 반환하는 함수이다 -> seonyounggg.tistory.com/120 )

즉, 두번째 원소(우선순위값) 값을 비교하여서 하나라도 큰게 있다면 뒤에 덧붙이는 것이다.

그리고 어차피 확인해보고 조건에 맞던 안맞던 삭제/이동될 값이라서 일단 pop한 후에 비교하는 게 맥락 상 이해하기 좋은 것 같다.

def solution(priorities, location):
    answer = 0
    search, c = sorted(priorities, reverse=True), 0
    while True:
        for i, priority in enumerate(priorities):
            s = search[c]
            if priority == s:
                c += 1
                answer += 1
                if i == location:
                    break
        else:
            continue
        break
    return answer

우선순위 리스트를 내림차순으로 정렬하여 찾을 순서를 담은 리스트를 생성한다. 이 리스트의 원소를 차례대로 priorities 에서 찾는다.

현재 출력해야하는 순위의 원소를 찾았다면 출력하고, 아니라면 continue한다. 이 과정을 무한반복한다.

( for-else구문을 처음 알게되었다. break없이 빠져나온 경우 else문이 실행된다. -> seonyounggg.tistory.com/122 )

즉, 원하는 원소를 찾지 못할 경우 다시 처음으로 돌아가서 실행한다. 찾는 위치의 원소를 만났을 경우 break하고 while문도 break한다.

시간 복잡도면에서는 좋지 않을 것 같은 풀이이지만 새로워서 기록하였다.

✏️ 생각

아무 생각없이 apped한 결과를 리스트에 다시 대입해놓는 바람에

list에 자꾸 None이 대입돼서 알아채는데 한참 걸렸다😂

짜증나서 슬라이싱으로 바꿔버림..ㅎㅎ

append()의 반환값은 None임을 명심하자!