본문 바로가기
개발공부_Blog/Algorithm

프로그래머스 - 다리를 지나는 트럭

by 소팡팡 2024. 11. 20.

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

< 문제 > 
트럭 여러 대가 강을 가로지르는 일차선 다리를 정해진 순으로 건너려 합니다. 
다리에는 트럭이 최대 bridge_length대 올라갈 수 있으며, 
다리는 weight 이하까지의 무게를 견딜 수 있습니다. 
다리에 완전히 오르지 않은 트럭의 무게는 무시합니다.

예를 들어, 트럭 2대가 올라갈 수 있고 무게를 10kg까지 견디는 다리가 있습니다. 
무게가 [7, 4, 5, 6]kg인 트럭이 순서대로 
최단 시간 안에 다리를 건너려면 다음과 같이 건너야 합니다.

 

최초의 아이디어

  • 일단 큐를 사용해야 한다는 점
  • 다리 위의 상태를 변수로 표현하는 것
  • 다리 위로 올라간 트럭의 무게를 변수로 표현하는 것

위와 같은 데이터 구조와 변수를 생각해 냈다는 점은 칭찬하지만, 그럼에도 구현상의 논리적 흐름에 구멍이 컸다. 다리 위로 트럭을 올려 시간을 추가하는 것까지 생각해 구현했지만 다리를 지나가고 난 다음의 상태, 다리 위 트럭의 갯수를 고려하지 못했다.

 

< v1. 코드 구현 흐름 >

  • bridge배열이 비어있으면
    • 트럭을 추가하고, 1초가 경과된 시간도 추가한다
  • 다리가 비어있지 않으면
    • 다리 위에 올라간 트럭의 무게와 다리가 지탱할 수 있는 트럭의 무게를 비교해서 다리에 트럭을 추가하거나 이전 트럭을 뺀다.
    function solution(bridge_length, weight, truck_weights) {
      let time = 0;
      let bridges = [];
    
      let bridgeSum = 0;
      bridges.forEach((item) => (bridgeSum += item));
    
      // while (truck_weights.length > 0) {
      for (let i = 0; i < truck_weights.length; i++) {
        if (bridges.length === 0) {
          // 다리가 비어있으면
          bridges.push(truck_weights[i]);
          time += 1;
        } else if (bridges.length < bridge_length) {
          // 다리가 비어있지 않으면
          time += 1;
          if (bridgeSum < weight) {
            // 다리 무게가 weight보다 작으면
            bridges.push(truck_weights[i]);
            time += 1;
          } else {
            // 다리 무게가 weight보다 크면
            bridges.shift();
            truck_weights.shift();
          }
        } else {
          time += 1;
        }
      }
      // }
      return time;
    }
    

< 보충해야 할 점 >

  • for와 while반복문을 사용했지만 for반복문의 기준이 되는 truck_weight의 길이를 shift()로 줄이고 있기 때문에 명확한 반복문이 되지 않았던 점, while이 자꾸 무한반복 되는 점ㅋㅋㅋㅋㅋ ( 코드 상의 이해가 부족 )
  • 데이터로 초기화 해야 하는 값들에 대한 설정이 부족함 ( bridgeSum, 반복문 밖에서 값을 더해주고 있음. 데이터 반영이 잘 안됨 / bridge 빈배열 )
  • 모든 트럭이 다리를 지나가는 시간에 대한 값을 정확히 체크하고 있는지의 여부가 불확실함 ( 매 조건문마다 time을 추가해주는데….흠…. )
  • 트럭이 다리에 올라간 것과 내려간 부분의 표현이 애매함 ( 올라간 것은 있지만 내려간 것은 없다 )

 

< v2. 코드 구현 흐름 >

  • bridges 다리에 올라갈 수 있는 트럭의 수를 queue로 표현할 수 있도록 트럭의 수만큼 배열로 초기화함.
    • 다리에 올라간 트럭과 지나간 트럭을 push와 shift를 사용해 표현함
    • 트럭을 추가할 때 weight보다 크다면 0을 넣어서 트럭이 올라오지 않게 설정함
    • shift를 통해 bridges의 공간을 빼줌.
    ⇒ bridges의 순환이 잘 이루어짐
  • 반복문의 처음부분에 time을 추가해줌. if조건문에 따라 time을 추가했던 부분을 맨위로 올림 ⇒ 모든 행위의 시작에는 1초가 흐르기 때문에.
  • while반복문만 사용함. ( truck_lenght가 0이 될 때까지 )
function solution(bridge_length, weight, truck_weights) {
  let answer = 0;
  **let bridges = Array(bridge_length).fill(0);**
  let bridgeSum = 0;
  console.log(bridges);

  while (truck_weights.length > 0 || bridges.length > 0) {
    answer++;
    
    // 1. 다리를 건넌 트럭 제거
    const truck = bridges.shift();
    bridgeSum -= truck; // 다리 위 무게에서 제거

    // 2. 새로운 트럭 추가 가능 여부 확인
    if (truck_weights.length > 0) {
      if (bridgeSum + truck_weights[0] <= weight) {
        const newTruck = truck_weights.shift(); // 대기 트럭을 다리 위로 올림
        bridges.push(newTruck);
        bridgeSum += newTruck; // 다리 위 무게 갱신
      } else {
        **bridges.push(0); // 트럭을 추가할 수 없으면 빈 공간 유지**
      }
    }
  }
  return answer;
}

console.log(solution(2, 10, [7, 4, 5, 6])); //	8
// console.log(solution(100, 100, [10])); //	101
// console.log(solution(100, 100, [10, 10, 10, 10, 10, 10, 10, 10, 10, 10])); //	110

 

 

전체적으로 논리적인 흐름을 잘 구성하는 게 먼저임을 오늘도 깨닫는다!! 헤헷,

댓글