Queue

Declare deque

We can declare queue with no initial data, or with a starting position.

queue = deque()
queue = deque([start_index, end_index])
queue = deque(some_list)

.peek() = deque[0]

We peek queue’s front-most element via deque[0]. Btw for stack it is [-1].

popleft()

If using it as a queue, popleft() removes the front-most element. For stack, it is just pop()

append((whatever elements in a list))

Unlike list, deque’s append is different. In list, we do .append([list of elements]) but in deque, we don’t use the square brackets but instead use circular brackets. If you are adding a tuple like (dx,dy) and an int like cost to deque, we do

deque.append(((x,y),cost))

!queue.isEmpty() = while(queue)

I kept on using while stack or while queue without knowing what it really meant but the while loop goes on as long as there is something in the queue or stack.

Practice questions

기능개발

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

I tried calculating the day of each progress and if current day is less than the recorded previous day(count), then we just increment hola, which I am gonna append it to list when the opposite condition comes.

3 problems: 1) The variable hola was being incremented but not reset to 0 when a new deployment set started. This caused incorrect counting of features deployed on the same day.

2) The condition if day <= count was incorrect. It should be if day > count because if the current day is greater than the previous maximum day (count), it indicates a new set of features will be deployed.

3) The code was missing the handling of the last set of features deployed. It did not append the count of the last set to the answer list.

Biggest mistake is appending hola when hola is 0.

Wrong initial code:

import math

def solution(progresses, speeds):
    # queue = deque(progresses)
    hola=0
    count=0
    answer = []
    
    for progress,speed in zip(progresses,speeds):
        day = math.ceil((100-progress)/speed)
        if day<=count:
            hola+=1
            count=day
            continue
        else:
            answer.append(hola)
        
    return answer

So correct code is

import math

def solution(progresses, speeds):
    count = 0
    hola = 0
    answer = []
    
    for progress, speed in zip(progresses, speeds):
        day = math.ceil((100 - progress) / speed)
        
        if day <= count:
            hola += 1
        else:
            count = day
            if hola > 0:
                answer.append(hola)
            hola = 1
    
    answer.append(hola)  # Append the count of the last set
    
    return answer

or

def solution(progresses, speeds):
    count = 0
    hola = 0
    answer = []
    
    for progress, speed in zip(progresses, speeds):
        day = math.ceil((100 - progress) / speed)
        
        if day > count:
            count = day
            if hola > 0:
                answer.append(hola)
                hola = 0
        
        hola += 1
    
    answer.append(hola)  # Append the count of the last set
    
    return answer

Or you can append hola right away and edit that element in list like

def solution(progresses, speeds):

    count=0
    answer = []
    
    for progress,speed in zip(progresses,speeds):
        day = math.ceil((100-progress)/speed)
        if day>count:
            count=day
            answer.append(0)

        #   editing last element in list
        answer[-1]+=1
        
    return answer

Or you can edit progresses list with increasing day number like diagram here https://happy-obok.tistory.com/38 Code:

def solution(progresses, speeds):
    #결과를 담을 리스트
    answer = []
    #작업 리스트가 빌 때까지 반복
    while progresses :
        #몇개의 기능이 배포되는지 저장 
        cnt = 0
        #작업 리스트가 남아있고 맨 앞의 작업의 진도가 100인 경우: 기능 배포 변수 증가. 해당 작업과 작업 속도를 리스트에서 제거
        while progresses and progresses[0] >= 100:
            cnt+=1
            progresses.pop(0)
            speeds.pop(0)

        # 작업 리스트의 진도를 증가
        progresses = [progresses[i]+speeds[i] for i in range(len(progresses))]

        #만약 오늘 기능이 배포되었다면 결과리스트에 추가
        if cnt:
            answer.append(cnt)
    
    return answer

I always sturggled taking care of the last case not being handled by my logic My code would have been like

def solution(progresses, speeds):

    answer = []
    time = 0
    count = 0
    
    while len(progresses)> 0:
        if (progresses[0] + time*speeds[0]) >= 100: 
            progresses.pop(0)
            speeds.pop(0)
            count += 1
            
        else:
            if count > 0:
                answer.append(count)
                count = 0
            time += 1
        
    #     taking care of last case
    answer.append(count)
    return answer

But I guess the code on top is better cuz it handles last case by placing variable count within the while loop

프로세스

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

While my thinking is right, if there are duplicate values of same priority in queue, it gets whatever that value comes first in the list.

Wrong code

def solution(p, location):
    maxCount = max(p)
    q = p.copy()
    
    while q:
        if q[0]<maxCount:
            q.append(q.pop(0))
        else:
            break
    ori_value = p[location]
    return q.index(ori_value)+1

Correct code:

from collections import deque

def solution(p, location):
    maxCount = max(p)
    queue = deque([(v, i+1) for i, v in enumerate(p)])

    count = 1
    while True:
        v, i = queue.popleft()
        if v < maxCount:
            queue.append((v, i))
        else:
            if i == location + 1:
                return count
            count += 1
            maxCount = max(queue)[0]

Or you can use any() like

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

주식가격

https://school.programmers.co.kr/learn/courses/30/lessons/42584 oH i misunderstood the question. Once you see a price that is lower than the current price that is popped off, we only consider that duration. Even if there is a higher price later on in the queue, we don’t consider that. So we break out of the loop instead of continue. Before we break out of the loop, we increment count because when time=0, it is considered meeting the condition. Wrong code:

from collections import deque

def solution(prices):
    queue = deque(prices)
    answer = []
    while queue:
        price = queue.popleft()
        count=0
        for q in queue:
            if q>=price:
                count+=1
            else:
                continue
        answer.append(count)
    return answer

You should not continue when exception is occurred. Instead, you should break out of loop like

correct:

from collections import deque

def solution(prices):
    queue = deque(prices)
    answer = []
    
    while queue:
        price = queue.popleft()
        count = 0
        
        for q in queue:
            if q >= price:
                count += 1
            else:
                count += 1
                break
        
        answer.append(count)
    
    return answer

Correct code

from collections import deque

def solution(prices):
    queue = deque(prices)
    answer = []
    while queue:
        price = queue.popleft()
        count=0
        for q in queue:
            count+=1
            if price>q:
                break

        answer.append(count)
    return answer

using stack

def solution(prices):
    answer = [0] * len(prices)
    stack = []

    for i in range(len(prices)):
        while stack != [] and stack[-1][1] > prices[i]:
            past_idx, _ = stack.pop()
            answer[past_idx] = i - past_idx

        stack.append([i, prices[i]])

    for i, _ in stack:
        answer[i] = len(prices) - i - 1

    return answer

다리를 지나는 트럭 (hard)

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

This is the question where you implement the way a human would solve this problem. You actually create a queue bridge of 0s of length bridge_length. And append and pop the truck accordingly

from collections import deque

def solution(bridge_length, weight, truck_weights):
    bridge = [0 for _ in range(bridge_length)]
    queue = deque(bridge)
    waiting = deque(truck_weights)
    time = 0
    bridge_weight=0
    while len(waiting)>0 or bridge_weight>0:
        cur_weight = queue.popleft()
        bridge_weight-=cur_weight
        if waiting and bridge_weight+waiting[0]<=weight:
            bridge_weight+=waiting[0]
            queue.append(waiting[0])
            waiting.popleft()
        else:
            queue.append(0)
        time+=1
        
    return time

while bridge_weight>0: this is very important because as long as there is a truck in our queue bridge currently passing, it needs to finish crossing regardless of whether the waiting queue of all trucks is empty.

[Fix 25th June] fuck i keep misunderstanding this if waiting condition. If waiting means if there is any element left in our waiting queue, not the other way around where if it is empty.

두 큐 합 같게 만들기

initial thinking code

def solution(queue1, queue2):
    pointer1 =0
    pointer2=0
    count =0
    for i in range(len(queue1),len(queue2)):
        sum1 = sum(queue1)
        sum2 = sum(queue2)
        if sum1==sum2:
            return count
        elif sum1<sum2:
            if queue2[pointer2] > queue1[pointer1]:
                queue1.append(queue2[pointer])
                pointer1+=1
                sum1+=queue2[pointer2]
                count+=1
            elif queue2[pointer2] < queue1[pointer1]:
                queue2.append(queue1[pointer1])
                pointer2+=1
                sum2 += queue1[pointer1]
                count +=1
            else:
                val1 = queue1.popleft()
                queue1.append(val)
                val2 = queue2.popleft()
                queue2.append(val)
        else:
            if queue2[pointer2] > queue1[pointer1]:
                queue1.append(queue2[pointer])
                pointer1+=1
                sum1+=queue2[pointer2]
                count+=1
            elif queue2[pointer2] < queue1[pointer1]:
                queue2.append(queue1[pointer1])
                pointer2+=1
                sum2 += queue1[pointer1]
                count +=1
            else:
                val1 = queue1.popleft()
                queue1.append(val)
                val2 = queue2.popleft()
                queue2.append(val)
    return count

correct: https://velog.io/@isayaksh/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-Programmers-%EB%91%90-%ED%81%90-%ED%95%A9-%EA%B0%99%EA%B2%8C-%EB%A7%8C%EB%93%A4%EA%B8%B0-Python we iterate up till 3 times the length of queue1, as explained by that link

from collections import deque
def solution(queue1, queue2):
    answer = 0
    queue1, queue2 = deque(queue1), deque(queue2)
    sum1, sum2 = sum(queue1), sum(queue2)
    for i in range(len(queue1)*3):
        if sum1>sum2:
            sum1-=queue1[0]
            sum2+=queue1[0]
            queue2.append(queue1.popleft())
            answer+=1
        elif sum2>sum1:
            sum2-=queue2[0]
            sum1+=queue2[0]
            queue1.append(queue2.popleft())
            answer+=1
        else:
            return answer
    return -1