Table of Contents

코딩테스트

[파이썬] 스택/큐 > 기능개발

꼬꼬마코더 2024. 5. 23. 15:33
728x90

코드연습 1 첫번째 코드

https://school.programmers.co.kr/learn/courses/30/lessons/42586

어머, 이 문제는 쉽네 하며 열심히 코드를 짜보았습니다. 

#1번째 코드
from collections import deque
import math
def solution(progresses, speeds):

    took_time = [math.ceil((100-item)/speeds[idx]) for idx, item in enumerate(progresses)]
    took_time_q = deque(took_time)
    cnt = 0
    result=[]
    

    while took_time_q:
        for item in took_time[1:]:
            if took_time_q[0] >= item:
                took_time_q.popleft()
                cnt += 1
            else:
                took_time_q.popleft()
                cnt += 1
        result.append(cnt)

    return result


print(solution([93, 30, 55],[1, 30, 5]))

IndexError: deque index out of range 에러를 내뱉으며 또 다시 절망에 빠뜨리는 나의 코드.

그렇습니다. 큐는 인덱스 슬라이싱을 제공하지 않는 것이었습니다. 다시 도전해봅니다.

 

코드연습 2 두번째 코드

#2번째 코드
from collections import deque
import math
def solution(progresses, speeds):

    took_time = [math.ceil((100-item)/speeds[idx]) for idx, item in enumerate(progresses)]
    took_time_q = deque(took_time)
    cnt = 0
    result=[]
    
    bigger = took_time_q.popleft()
    
    while took_time_q:
        for idx, item in enumerate(took_time_q):
            if bigger >= item:
                took_time_q.popleft()
                cnt += 1
        result.append(cnt)

    return result

RuntimeError: deque mutated during iteration 그렇습니다. 큐는 enumerate기능도 제공하지 않는 것이었습니다. 그리고 제 코드는 무한루프를 도는 것 같습니다. 다시 도전해보았습니다.

코드연습 3 세번째 코드

#3번째 코드
from collections import deque
import math
def solution(progresses, speeds):

    took_time = [math.ceil((100-item)/speeds[idx]) for idx, item in enumerate(progresses)]
    took_time_q = deque(took_time)
    
    result=[]
    
    
    
    while took_time_q:
        bigger = took_time_q.popleft()
        took_time = took_time[1:]
        cnt = 1
        
        for idx, item in enumerate(took_time):
            if bigger >= item:
                took_time_q.popleft()
                took_time = took_time[1:]
                cnt += 1
        result.append(cnt)

    return result

이번엔 머리를 써서 bigger 비교변수를 만들어 줬습니다. 그러나 2개 중 1개만 성공했네요. 다시 도전해봅니다.

코드연습 4 네번째 코드

#4번째 코드
from collections import deque
import math
def solution(progresses, speeds):

    took_time = [math.ceil((100-item)/speeds[idx]) for idx, item in enumerate(progresses)]
    took_time_q = deque(took_time)
    
    result=[]
    
    
    
    while took_time_q:
        bigger = took_time_q.popleft()
        took_time = took_time[1:]
        cnt = 1
        
        for idx, item in enumerate(took_time):
            if bigger >= item:
                took_time_q.popleft()
                took_time = took_time[1:]
                cnt += 1
            else: 
                break
        result.append(cnt)

    return result


성공했습니다! 이제 제 코드를 GPT선생님에게 드리고 수정할 부분이 있는지 물어보겠습니다.


당신의 코드는 전반적으로 잘 작성되었습니다. 그러나 몇 가지 비효율성과 수정이 필요한 부분이 있습니다. 특히 took_time 리스트를 슬라이싱하는 부분에서 비효율성이 발생합니다. deque를 사용하므로 이 부분을 최적화할 수 있습니다.

코드연습 GPT 정답코드

다음은 최적화된 버전의 코드입니다:

from collections import deque
import math

def solution(progresses, speeds):
    # 각 작업이 완료되는 데 걸리는 일수를 계산합니다.
    took_time = [math.ceil((100 - item) / speeds[idx]) for idx, item in enumerate(progresses)]
    took_time_q = deque(took_time)
    
    result = []
    
    while took_time_q:
        # 첫 번째 작업이 완료되는 시간
        bigger = took_time_q.popleft()
        cnt = 1
        
        # 다음 작업들이 앞선 작업과 함께 배포될 수 있는지 확인합니다.
        while took_time_q and took_time_q[0] <= bigger:
            took_time_q.popleft()
            cnt += 1
        
        result.append(cnt)

    return result

# 테스트
progresses = [93, 30, 55]
speeds = [1, 30, 5]
print(solution(progresses, speeds))  # 출력: [2, 1]

 

이 코드는 다음과 같은 방식으로 작동합니다:

  1. took_time 리스트를 계산하여 각 작업이 완료되는 데 필요한 일수를 구합니다.
  2. took_time_q로 deque를 생성합니다.
  3. while 루프를 사용하여 deque가 빌 때까지 작업을 처리합니다.
    • 첫 번째 작업의 완료 시간을 bigger에 저장합니다.
    • 그 다음 작업들이 bigger보다 작은 경우 함께 배포될 수 있으므로 while 루프를 사용하여 계속 popleft합니다.
  4. 함께 배포되는 작업의 수를 result 리스트에 추가합니다.
  5. 최종 결과를 반환합니다.

이 방법은 deque를 활용하여 효율적으로 작업을 처리합니다. took_time 리스트를 매번 슬라이싱할 필요 없이 deque에서 popleft 메서드를 사용하여 첫 번째 요소를 제거합니다. 이를 통해 코드의 효율성을 높였습니다.


아하...for문을 돌면서 took_time 리스트로 bigger와 아이템을 비교하는 대신에

while문을 한 번 더 써줌으로써 bigger와  took_time_q[0]를 비교하면 되는거군요!

저 바보인가요? 저걸 몰라서 리스트와 큐를 동시에 썼습니다....

그러면 다시 한 번 짜보겠습니다.

코드연습 5 다섯번째 코드

#5번째 코드
from collections import deque
import math
def solution(progresses, speeds):

    took_time = [math.ceil((100-item)/speeds[idx]) for idx, item in enumerate(progresses)]
    took_time_q = deque(took_time)
    
    result=[]
    
    
    
    while took_time_q:
        bigger = took_time_q.popleft()
        cnt = 1
        
        while took_time_q and bigger >=took_time_q[0]:
            took_time_q.popleft()
            cnt += 1

        result.append(cnt)

    return result

성공했습니다.

 

큐는 전부 다 이런 방식의 문제들인 것 같습니다.

먼저 초기 변수를 셋팅하고

while 문을 만든 다음

popleft를 해서 비교할 수 있는 비교변수를 만들어줍니다.

그리고 다시 while문을 만들어 비교변수와 비교하는거죠.