[백준14891_자바스크립트(javascript)] - 톱니바퀴

경이·2024년 9월 11일

𝑩𝑶𝑱 (𝒋𝒔)

목록 보기
177/325

🔴 문제

톱니바퀴


🟡 Sol

const fs = require('fs');
const path = process.platform === 'linux' ? '/dev/stdin' : 'Wiki\\input.txt';
const inputs = fs.readFileSync(path).toString().trim().split('\n');
const wheels = inputs.splice(0, 4).map((it) => it.split('').map(Number));
const k = Number(inputs.splice(0, 1));

const printMap = (...param) => {
  const map = wheels;
  for (let i = 0; i < map.length; i++) console.log(map[i].join(' '));
  console.log(...param);
};

const isRotate = (w, d) => {
  if (d === -1) return wheels[w - 1][2] !== wheels[w][6];
  else return wheels[w][2] !== wheels[w + 1][6];
};

const rotate = (w, d) => {
  if (d === 1) wheels[w].unshift(wheels[w].pop());
  else wheels[w].push(wheels[w].shift());
};

for (const input of inputs) {
  let [w, d] = input.split(' ').map((it, idx) => (idx ? Number(it) : it - 1));
  let rotateQ = [false, false, false, false];

  rotateQ[w] = d;
  if (w === 0) {
    if (isRotate(1, -1)) {
      rotateQ[1] = d * -1;
      if (isRotate(2, -1)) {
        rotateQ[2] = d;
        if (isRotate(3, -1)) {
          rotateQ[3] = d * -1;
        }
      }
    }
  }

  if (w === 1) {
    if (isRotate(0, 1)) {
      rotateQ[0] = d * -1;
    }
    if (isRotate(2, -1)) {
      rotateQ[2] = d * -1;
      if (isRotate(3, -1)) {
        rotateQ[3] = d;
      }
    }
  }

  if (w === 2) {
    if (isRotate(1, 1)) {
      rotateQ[1] = d * -1;
      if (isRotate(0, 1)) {
        rotateQ[0] = d;
      }
    }
    if (isRotate(3, -1)) {
      rotateQ[3] = d * -1;
    }
  }

  if (w === 3) {
    if (isRotate(2, 1)) {
      rotateQ[2] = d * -1;
      if (isRotate(1, 1)) {
        rotateQ[1] = d;
        if (isRotate(0, 1)) {
          rotateQ[0] = d * -1;
        }
      }
    }
  }

  for (let i = 0; i < 4; i++) {
    if (!rotateQ[i]) continue;
    rotate(i, rotateQ[i]);
  }
}

let ans = 0;
for (let i = 0; i < 4; i++) {
  if (wheels[i][0]) ans += Math.pow(2, i);
}
console.log(ans);

🟢 풀이

⏰ 소요한 시간 : 2시간 그 이상..

실수하기 쉽지만 어렵지 않은문제라는데
왤케 어려웠는지 모르겠다... 시뮬레이션 유형인데 따져줘야 할 게 많다.(시뮬레이션이니까)

어떻게 해야될지 감이 안와서 그냥 모든 경우의 수를 따져주었다. 일단 맨 위의 printMapwheels를 직관적으로 볼 수 있기 위한 디버깅 용 함수다.

isRotate는 이 바퀴가 돌아가는지 아닌지를 체크하는데, 몇 번바퀴인지 알려주는 w와 내 왼쪽을 확인할건지 오른쪽을 확인할건지 알려주는 방향변수 d를 매개변수로 받는다. d-1라면 내 왼쪽 바퀴랑 확인을 하고, d1이라면 오른쪽 바퀴와 확인을 한다.

rotate는 실제로 바퀴를 돌려주는 함수인데 마찬가지로 몇 번바퀴를 돌리지 알려주는 w와 어느방향으로 돌릴지 알려주는 변수 d를 받는다.
d1이라면 오른쪽으로 돌려주고, d-1 이라면 왼쪽으로 돌려준다.

코드는 for문부터 시작된다. 입력받은 inputs를 순회하며 바퀴를 돌려주는데 예를들어 1번 바퀴를 돌리면 2번바퀴는 1번 바퀴를 돌리기 전 상태로 영향을 받는다. 따라서 바퀴를 바로 돌려주지 않고, 바퀴를 돌릴지 말지를 결정하는 큐 rotateQ를 만들어 줬다.
문제에서는 w번 바퀴를 d방향으로 회전해줘야 하니까 일단 rotateQw번째 인덱스를 d번 방향으로 회전할 수 있도록 바꿔준다.

그 다음에 w1번 바퀴라면 2번을 확인해줘야 한다. 1번으로부터 영향을 받았기 때문에 왼쪽바퀴를 확인해야하므로 isRoate(1, -1)이 들어간다. 이 때 배열은 0부터 시작하므로 2번바퀴를 확인해야하지만 1번을 확인할 수 있도록 wd를 포매팅 하는과정에서 1씩 빼주었다. 2번 바퀴가 돌아가면 3번 바퀴의 조건을 수행할 수 있도록 3번 바퀴가 돌아가면 4번 바퀴의 조건을 수행할 수 있도록 할텐데 만약 각 바퀴가 모두 돌아간다면 rotateQ의 값을 업데이트 해주되, d의 방향에 신경쓰며 고쳐준다.

나머지 요소도 모두 동일하게 처리한 뒤 바퀴를 돌릴지 말지를 결정하는 rotateQ를 순회하며 실제로 바퀴를 돌려준다.

모든 과정을 마치면 wheels를 순회하며 12시를 가르키는 바퀴의 0번째 요소가 1인지 아닌지를 판단하여 점수를 매겨준다.

바퀴가 만약 10개라면 코드가 훨씬 복잡했을 것이다.
그래서 같이 스터디하는 분들의 코드를 살펴봤는데 아예 바퀴의 상태를 복사한 newWheel을 만들고 wheels과 명령을 비교하여 newWheel에 반영한다. 그리고 모든 경우의 수를 하드 코딩 하지 않고 이렇게 for문을 사용해서 풀면 더 간단할 것 같다.

for (let i = target + 1; i < 4; i++) { 
  if (wheels[i][6] !== wheels[i - 1][2]) {
      d = -d;
      newWheels[i] = rotate(wheels[i], d);
  }
  else {
      break; 
  }
}

내 바퀴 기준 오른쪽에 있는 요소만 확인하면 되는 코드다.


🔵 Ref

profile
록타르오가르

0개의 댓글