본문 바로가기

코딩 테스트/프로그래머스

[Python] 프로그래머스 lv.2 다리를 지나는 트럭

알고리즘 고득점 kit - 스택/큐

 

정답 코드

from collections import deque
def solution(bridge_length, weight, trucks):
    time = 0
    bridge = deque([0] * bridge_length) # 다리 상태
    trucks = deque(trucks) # 대기 트럭 큐
    current_weight = 0 # 현재 다리 위의 총 무게

    while trucks or current_weight > 0 : # 대기 트럭이 있거나, 대기 트럭이 없다면 다리에서 다 내려갈때까지
        time += 1 # 트럭이 다리를 모두 내려울 때까지 시간이 경과됨

        # 다리에서 맨 앞의 트럭이 내려옴 / 만약 맨 앞에 트럭이 없었다면 아무 일도 일어나지 않음 (-0)
        exited_truck = bridge.popleft()
        current_weight  -= exited_truck

        # 대기 중인 트럭이 다리 위에 올라갈 수 있는가?
        if trucks and current_weight + trucks[0] <=  weight :
            truck = trucks.popleft()
            bridge.append(truck)
            current_weight += truck
        else : # 다리 위에 못올라가면 빈 공간 유지
            bridge.append(0)

    return time

 

2회차 - 2024.11.27

문제 분석

  • 일차선 다리를 순서대로 건너려고 하는데, 모든 트럭이 다리를 건너려면 최소 몇 초가 걸리는가
  • 다리위에 최대 bridge_length대의 트럭이 올라갈 수 있다.
  • 다리는 weight 이하의 무게를 견딜 수 있다.
  • 다리에 아직 오르지 않은 트럭의 무게는 무시

 

코드 설계

  • 한 번에 올릴 수 있는 만큼 다리 위에 트럭 올리기
  • bridge_length 만큼의 트럭을 하나씩 올리는데 만약 올렸을 때 weight를 넘기면 더 이상 올리지 않음
  • 최종적으로 다리 위에 올라간 트럭은 대기 트럭 리스트에서 삭제
  • 최대한 올리면 삭제 (다리를 지난 트럭)
  • 삭제할 때 1개씩 삭제하는데 그때마다 time+1
  • 트럭을 옮기려고 시도할 때나 트럭의 위치가 변할 때마다 time+1
  • 트럭을 다리에 최대한 옮기려고 시도하거나 지울때나..
  • 트럭이 다리에 올라가면 대기 트럭에서 지워지는 부분 구현 실패
  • 다리 위에 올라갈 수 있는 트럭의 최대 수보다 대기 트럭의 수가 적을 때 부분 구현 실패

 

정답 코드

실패..

def solution(bridge_length, weight, truck_weights):
    time = 0
    bridge = []
    
    while truck_weights : 
        # 다리 위에 트럭 올리기
        # 다리 위에 올라간 트럭은 대기 트럭 리스트에서 삭제
        for i in range(bridge_length) : 
            bridge.append(truck_weights[i])
            time += 1 # 시도 해도 시간이 간다..
            if sum(bridge) > weight : 
                del truck_weights[i]
                break
                
        time += len(bridge) # 지나가는 수만큼
        bridge.clear()

    return time

 

다른 사람 코드 1

import collections

DUMMY_TRUCK = 0


class Bridge(object):

    def __init__(self, length, weight):
        self._max_length = length
        self._max_weight = weight
        self._queue = collections.deque()
        self._current_weight = 0

    def push(self, truck):
        next_weight = self._current_weight + truck
        if next_weight <= self._max_weight and len(self._queue) < self._max_length:
            self._queue.append(truck)
            self._current_weight = next_weight
            return True
        else:
            return False

    def pop(self):
        item = self._queue.popleft()
        self._current_weight -= item
        return item

    def __len__(self):
        return len(self._queue)

    def __repr__(self):
        return 'Bridge({}/{} : [{}])'.format(self._current_weight, self._max_weight, list(self._queue))


def solution(bridge_length, weight, truck_weights):
    bridge = Bridge(bridge_length, weight)
    trucks = collections.deque(w for w in truck_weights)

    for _ in range(bridge_length):
        bridge.push(DUMMY_TRUCK)

    count = 0
    while trucks:
        bridge.pop()

        if bridge.push(trucks[0]):
            trucks.popleft()
        else:
            bridge.push(DUMMY_TRUCK)

        count += 1

    while bridge:
        bridge.pop()
        count += 1

    return count


def main():
    print(solution(2, 10, [7, 4, 5, 6]), 8)
    print(solution(100, 100, [10]), 101)
    print(solution(100, 100, [10, 10, 10, 10, 10, 10, 10, 10, 10, 10]), 110)


if __name__ == '__main__':
    main()

 

다른 사람 코드 2

from collections import deque

def solution(bridge_length, weight, truck_weights):
    bridge = deque(0 for _ in range(bridge_length))
    total_weight = 0
    step = 0
    truck_weights.reverse()

    while truck_weights:
        total_weight -= bridge.popleft()
        if total_weight + truck_weights[-1] > weight:
            bridge.append(0)
        else:
            truck = truck_weights.pop()
            bridge.append(truck)
            total_weight += truck
        step += 1

    step += bridge_length

    return step