Algorithm

[백준] 7562번: 나이트의 이동 - Node.js (자바스크립트)

sqsung 2023. 5. 23. 13:36

1. 문제 ㅡ 7562번: 나이트의 이동(난이도: Silver I)

7562번: 나이트의 이동

체스판 위에 한 나이트가 놓여져 있다. 나이트가 한 번에 이동할 수 있는 칸은 아래 그림에 나와있다. 나이트가 이동하려고 하는 칸이 주어진다. 나이트는 몇 번 움직이면 이 칸으로 이동할 수

www.acmicpc.net

 

2. 풀이 ㅡ Node.js (자바스크립트)

const [N, ...input] = require('fs').readFileSync('/dev/stdin').toString().trim().split('\n');

const solution = input => {
  // 나이트가 이동할 수 있는 방향들  
  const moves = [[-1, 2], [-2, 1], [-2, -1], [-1, -2], [1, -2], [2, -1], [2, 1], [1, 2]];
  const testCases = [];
  const answers = [];

  // 테스트 케이스들 숫자 타입 정보를 가진 객체로 변경 및 testCases 배열에 저장 
  for (let i = 0; i < +N; i++) {
    // TypeError 이유 ▽
    const [board, start, end] = input.splice(0, 3);
    const tcObject = { board: +board, start: start.split(' ').map(val => +val), end: end.split(' ').map(val => +val) };

    testCases.push(tcObject);
  }

  // bfs 탐색 
  for (let i = 0; i < +N; i++) {
    const { board, start, end } = testCases[i];
    const checked = Array.from({ length: board }, () => Array.from({ length: board }, () => false));
    const queue = [[...start, 0]];

    while (queue.length) {
      const [x, y, count] = queue.shift();

	  // x, y 값이 end의 x, y와 같으면 누적된 count 저장 및 while문 break 
      if (x === end[0] && y === end[1]) {
        answers.push(count);
        break;
      }

      checked[y][x] = true;

      moves.forEach(move => {
        const xPos = x + move[0];
        const yPos = y + move[1];

        if (xPos < 0 || yPos < 0 || xPos >= board || yPos >= board || checked[yPos][xPos]) return;

        checked[yPos][xPos] = true;

        queue.push([xPos, yPos, count + 1]);
      });
    }
  }

  return answers.join('\n');
};

console.log(solution(input));

 

2-1. 풀이 설명

백준에서 BFS 유형 문제를 여러 개 풀어봤다면 금방 어떻게 풀어야할지 감이 올만한 문제다. 다른 문제에서는 주로 좌우상하로 인접한 칸만 확인했던 것과 달리, 이번 문제에서는 나이트가 이동할 수 있는 모든 칸을 확인하면 된다.
 
우선 각 테스트 케이스를 객체(tcObject)로 정리했다. 각 tcObject에는 나이트의 시작점과 목표점, 그리고 보드의 크기 정보를 저장해두었다. 이후 각 tcObject를 순회하면서 while문을 사용해 BFS 탐색을 했다. while문 내부에서는 현재 x, y 값이 종료점의 x, y와 일치하는지 확인하고, 일치하면 누적된 count 값을 answers 배열에 담아주고, 일치하지 않는 경우에는 해당 위치에서 또 나이트가 이동할 수 있는 칸을 queue에 담아 탐색을 반복했다.  
 

2-2. 회고

  • '체점현황' 탭을 누르고 언어를 node.js로 설정하면 많은 제출에 런타임 에러(TypeError)가 난걸 확인할 수 있다. 나 또한 VS Code에서는 아무 문제 없이 작동하는 코드가 제출만 하면 런타임 에러(TypeError)가 나서 답답했다.
  • 자바스크립트로 제출한 다른 개발자 분들의 경우 왜 런타임 에러(TypeError)가 났는지 정확히는 모르지만, 나 같은 경우에는 테스트 케이스 정보를 정리하는 과정에서 splice의 조건을 잘못 줘서 그렇게 됐다 (코드 블럭에서 'TypeError 이유' 부분 확인)
  • 정확히는 input에서 각 테스트 케이스를 분리하기 위해 splice 메서드를 사용했는데, 모든 테스트 케이스가 3줄이므로 splice(0, 3)하면 되는 걸 이상하게 splice(0, N)을 해줬다. 우연히도 문제에서 제공한 테스트 케이스에서는 N 또한 3이었으므로 문제없이 돌아갔지만, 테스트 케이스의 개수를 1개로 줄이고 돌려보고 나서야 문제를 찾았다.