백준 문제풀이 1063번 킹

[백준 문제풀이] 1063번 킹


1063번 킹 (Silver 3)

문제

https://www.acmicpc.net/problem/1063

8*8크기의 체스판에 왕이 하나 있다. 킹의 현재 위치가 주어진다. 체스판에서 말의 위치는 다음과 같이 주어진다. 알파벳 하나와 숫자 하나로 이루어져 있는데, 알파벳은 열을 상징하고, 숫자는 행을 상징한다. 열은 가장 왼쪽 열이 A이고, 가장 오른쪽 열이 H까지 이고, 행은 가장 아래가 1이고 가장 위가 8이다. 예를 들어, 왼쪽 아래 코너는 A1이고, 그 오른쪽 칸은 B1이다.

킹은 다음과 같이 움직일 수 있다.

R : 한 칸 오른쪽으로 L : 한 칸 왼쪽으로 B : 한 칸 아래로 T : 한 칸 위로 RT : 오른쪽 위 대각선으로 LT : 왼쪽 위 대각선으로 RB : 오른쪽 아래 대각선으로 LB : 왼쪽 아래 대각선으로 체스판에는 돌이 하나 있는데, 돌과 같은 곳으로 이동할 때는, 돌을 킹이 움직인 방향과 같은 방향으로 한 칸 이동시킨다. 아래 그림을 참고하자.

입력으로 킹이 어떻게 움직여야 하는지 주어진다. 입력으로 주어진 대로 움직여서 킹이나 돌이 체스판 밖으로 나갈 경우에는 그 이동은 건너 뛰고 다음 이동을 한다.

킹과 돌의 마지막 위치를 구하는 프로그램을 작성하시오.

입력

첫째 줄에 킹의 위치, 돌의 위치, 움직이는 횟수 N이 주어진다. 둘째 줄부터 N개의 줄에는 킹이 어떻게 움직여야 하는지 주어진다. N은 50보다 작거나 같은 자연수이고, 움직이는 정보는 위에 쓰여 있는 8가지 중 하나이다.

출력

첫째 줄에 킹의 마지막 위치, 둘째 줄에 돌의 마지막 위치를 출력한다.

소스코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
const fs = require("fs");
let [chessPieces, ...commands] = fs
  .readFileSync("/dev/stdin")
  .toString()
  .trim()
  .split("\n");

chessPieces = chessPieces.split(" ");
const N = chessPieces.pop();

solveProblem();

function solveProblem() {
  // 이동을 숫자의 증감으로 표현할 수 있도록
  // 열을 숫자로 변환함.
  chessPieces = positionToAscii(chessPieces);

  // 명령 배열을 돌며 명령 수행
  commands.forEach((command) => {
    chessPieces = handleCommand(chessPieces, command);
  });

  // 출력을 위해 다시 체스 포지션 문자열로 변경
  chessPieces = asciiToPosition(chessPieces);

  // 결과 출력
  console.log(chessPieces.join("\n"));
}

// 명령 수행
// @chessPieces {Array}: king, stone의 위치 정보를 담은 이차원 배열
// @command {String}: 명령 문자열
// @return {Array}: king, stone의 위치 정보를 담고 있는 이차원 배열
function handleCommand(chessPieces, command) {
  let [king, stone] = chessPieces;

  // king 이동.
  king = moveChessPiece(king, command);
  if (king[0] === stone[0] && king[1] === stone[1]) {
    // king과 store의 위치가 같으면,
    // stone도 이동시킴.
    stone = moveChessPiece(stone, command);
  }

  // 두 말의 위치가 보드 내에 있다면,
  // 변경된 위치 정보 반환
  if (checkPosition(...king) && checkPosition(...stone)) return [king, stone];

  // 두 말의 위치가 보드 밖에 있다면,
  // 변경전 위치 정보 반환
  return chessPieces;
}

// 체스말 이동 함수
// @chessPiece {Array} : 이동할 체스말 위치 정보
// @command {String}: 명령 문자열
function moveChessPiece(chessPiece, command) {
  let [movedColumn, movedRow] = chessPiece;

  switch (command[0]) {
    case "R":
      movedColumn++;
      break;
    case "L":
      movedColumn--;
      break;
    case "T":
      movedRow++;
      break;
    case "B":
      movedRow--;
      break;
  }

  if (command[1]) {
    switch (command[1]) {
      case "T":
        movedRow++;
        break;
      case "B":
        movedRow--;
        break;
    }
  }

  return [movedColumn, movedRow];
}

// 위치 확인 함수
// 체스말의 위치가 보드 내에 있는지 확인
// @column, row {String}: 체스말 열, 행 정보
// @return {Boolean}
function checkPosition(column, row) {
  if (column >= 65 && column <= 72 && row >= 1 && row <= 8) return true;

  return false;
}

// 체스판 위치 => 아스키코드 변환 함수
// @return {Array} : 아스키코드로 변환된 king, stone의 위치 정보 이차원 배열
function positionToAscii(chessPieces) {
  chessPieces = chessPieces.map((chessPiece) => {
    chessPiece = chessPiece.split("");
    chessPiece[0] = chessPiece[0].charCodeAt();
    chessPiece[1] = chessPiece[1] * 1;

    return chessPiece;
  });

  return chessPieces;
}

// 아스키코드 => 체스판 위치 변환 함수
// @return {Array} : 문자열로 변환된 king, stone의 위치 정보 배열
function asciiToPosition(chessPieces) {
  chessPieces = chessPieces.map((chessPiece) => {
    chessPiece[0] = String.fromCharCode(chessPiece[0]);
    chessPiece[1] = chessPiece[1] * 1;

    return chessPiece.join("");
  });

  return chessPieces;
}