스택,큐_다리위로 트럭지나가기

Mar 21st 2020 by jyoon

문제 설명

트럭 여러 대가 강을 가로지르는 일 차선 다리를 정해진 순으로 건너려 합니다. 모든 트럭이 다리를 건너려면 최소 몇 초가 걸리는지 알아내야 합니다. 트럭은 1초에 1만큼 움직이며, 다리 길이는 bridge_length이고 다리는 무게 weight까지 견딥니다.
※ 트럭이 다리에 완전히 오르지 않은 경우, 이 트럭의 무게는 고려하지 않습니다.

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

경과 시간	    다리를 지난 트럭	    다리를 건너는 트럭	     대기 트럭
0	          []	              []	                [7,4,5,6]
1~2	        []	              [7]	                [4,5,6]
3	          [7]	              [4]	                [5,6]
4	          [7]	              [4,5]	              [6]
5	          [7,4]	            [5]	                [6]
6~7	        [7,4,5]	          [6]	                []
8	          [7,4,5,6]	        []	                []

따라서, 모든 트럭이 다리를 지나려면 최소 8초가 걸립니다.

solution 함수의 매개변수로 다리 길이 bridgelength, 다리가 견딜 수 있는 무게 weight, 트럭별 무게 truckweights가 주어집니다. 이때 모든 트럭이 다리를 건너려면 최소 몇 초가 걸리는지 return 하도록 solution 함수를 완성하세요.

제한 조건

  • bridge_length는 1 이상 10,000 이하입니다.
  • weight는 1 이상 10,000 이하입니다.
  • truck_weights의 길이는 1 이상 10,000 이하입니다.
  • 모든 트럭의 무게는 1 이상 weight 이하입니다.

입출력 예

bridge_length	weight	truck_weights	                    return
2	            10	    [7,4,5,6]	                        8
100	          100	    [10]	                            101
100	          100	    [10,10,10,10,10,10,10,10,10,10]	  110

해결 방법

STEP1,2에서는 다리 위로 트럭이 지나갈 수 있는지 조건 사전 확인 단계, STEP3은 트럭이 다리위로 올릴 수 있는지 확인, STEP4는 트럭 이동, STEP5는 while문의 종단점(트럭이 다리를 다지나간 경우)

  • STEP1.

    • filter: 다리에서 트럭움직인 거리가 다리 길이보다 작은 것
  • STEP2.

    • 다리위에 있는 트럭 무게 계산
  • STEP3.

    • 트럭을 하나 더 다리위로 올릴 수 있을지 판단
    • 핵심: 다리 상태(올라가있는 트럭부게, 이동거리)를 확인할 수 있는 dictionary Object를 statusBridge배열에 push한다.
  • STEP4.

    • 트럭을 1만큼 움직인다.
  • STEP5.

    • 다리상태, 트럭을 담은 배열이 0이라면 while문을 벗어난다.

추가 정보: dictionary Object

  • "forEach, map"에서 배열 요소가 dictionary object가 인자인 배열은 dictionary Object property를 변경할 수 있다. 하지만 숫자만 있는 배열은 변하지 않는다.
  • dictionary object가 배열 요소로 있을 경우 map사용으로 새로운 배열을 만들어 내는것이 좋겠다.

    • map으로 순회할 대상 배열도 변경이 된다. 아래 map 예제에 확인 부분을 확인해보자
  • forEach에서
var a = [1, 2, 3]
a.forEach(v => ++v)
//a => [1,2,3]

var b = [{ dist: 1 }, { dist: 2 }, { dist: 3 }]
var bb = b.forEach(v => ++v.dist)
//b  => [{dist:2}, {dist:3}, {dist:4}]
//bb => [{dist:2}, {dist:3}, {dist:4}]
  • map에서
    map에서 확인
    var a = [1,2,3];
    var aa = a.map( v => ++v );
    //a  : [1,2,3]
    //aa : [2,3,4]

    var b = [{dist:1}, {dist:2}, {dist:3}];
    var bb = b.map( v => (++v.dist, v));
    //b  : [{dist:2}, {dist:3}, {dist:4}]   <- 확인!
    //bb : [{dist:2}, {dist:3}, {dist:4}]

CODE

function solution(bridge_length, weight, truck_weights) {
  var answer = 0
  var statusBridge = []

  while (true) {
    answer++

    //1. filter: 다리에서 트럭움직인 거리가 다리 길이보다 작은 것
    statusBridge = statusBridge.filter(o => o.dist < bridge_length)

    //2. 다리위에 있는 트럭 무게 계산
    let currentWeight = statusBridge
      .map(v => v.weight)
      .reduce((p, c) => p + c, 0)

    //3. 트럭을 하나 더 다리위로 올릴 수 있을지 판단
    if (weight - currentWeight >= truck_weights[0]) {
      let truck = {
        weight: truck_weights.shift(),
        dist: 0,
      }
      statusBridge.push(truck)
    }

    //4. 트럭을 1만큼 움직인다.
    statusBridge.map(o => (++o.dist, o))

    //5. 다리상태, 트럭을 담은 배열이 0이라면 while문을 벗어난다.
    if (!statusBridge.length && !truck_weights.length) break
  }

  return answer
}