연습장/백준(BOJ) 문제풀이
[백준 3190 - Node.js] 뱀
Tesseractjh
2022. 10. 23. 18:01
🔗 문제 링크
https://www.acmicpc.net/problem/3190
3190번: 뱀
'Dummy' 라는 도스게임이 있다. 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다. 게임
www.acmicpc.net
✏️ 풀이
const input = require('fs')
.readFileSync('/dev/stdin')
.toString()
.trim()
.split('\n');
const [N, K] = input.slice(0, 2).map(Number);
const apples = input.slice(2, 2 + K).map(v => v.split(' ').map(Number));
const rotations = input
.slice(K + 3)
.reduce((acc, v) => {
const [time, direction] = v.split(' ');
acc[time] = direction === 'L' ? -1 : 1;
return acc;
}, {});
const board = [...Array(N)].map(() => Array(N).fill(0));
apples.forEach(([x, y]) => board[x - 1][y - 1] = 2);
const offset = [[0, 1], [1, 0], [0, -1], [-1, 0]];
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}
class Queue {
constructor() {
this.size = 0;
this.head = null;
this.tail = null;
}
enqueue(value) {
const node = new Node(value);
if (!this.size) {
this.head = node;
this.tail = node;
} else {
this.head.next = node;
this.head = node;
}
this.size++;
}
dequeue() {
if (!this.size) {
return;
}
const deletedNodeValue = this.tail.value;
if (this.size === 1) {
this.head = null;
this.tail = null;
} else {
this.tail = this.tail.next;
}
this.size--;
return deletedNodeValue;
}
}
const snake = new Queue();
snake.enqueue([0, 0]);
let direction = 0;
let time = 0;
while (true) {
time++;
const [x, y] = snake.head.value;
const [dx, dy] = offset[direction];
const nx = x + dx;
const ny = y + dy;
if (nx < 0 || nx >= N || ny < 0 || ny >= N || board[nx][ny] === 1) {
break;
}
if (!board[nx][ny]) {
const [tx, ty] = snake.dequeue();
board[tx][ty] = 0;
}
snake.enqueue([nx, ny]);
board[nx][ny] = 1;
direction = (direction + 4 + (rotations[time] ?? 0)) % 4;
}
console.log(time);
board에 빈 칸은 0, 뱀이 있는 칸은 1, 사과가 있는 칸은 2로 표시하였다.
직접 큐를 구현하여 매 초마다 뱀을 이동시키면서 enqueue하고, 빈 칸으로 이동했을 때에는 뱀의 꼬리 칸을 dequeue하였다. 그리고 뱀의 머리가 이동할 칸이 board 범위 밖이거나 자기 자신의 몸일 경우에는 반복을 종료하도록 하였다.
✏️ 다른 풀이
const input = require('fs')
.readFileSync('/dev/stdin')
.toString()
.trim()
.split('\n');
const [N, K] = input.slice(0, 2).map(Number);
const apples = input.slice(2, 2 + K).map(v => v.split(' ').map(Number));
const rotations = input
.slice(K + 3)
.reduce((acc, v) => {
const [time, direction] = v.split(' ');
acc[time] = direction === 'L' ? -1 : 1;
return acc;
}, {});
const board = [...Array(N)].map(() => Array(N).fill(0));
apples.forEach(([x, y]) => board[x - 1][y - 1] = 2);
const offset = [[0, 1], [1, 0], [0, -1], [-1, 0]];
const snake = [[0, 0]];
board[0][0] = 1;
let direction = 0;
let tailIndex = 0;
let time = 0;
while (true) {
time++;
const [x, y] = snake[snake.length - 1];
const [dx, dy] = offset[direction];
const nx = x + dx;
const ny = y + dy;
if (nx < 0 || nx >= N || ny < 0 || ny >= N || board[nx][ny] === 1) {
break;
}
if (!board[nx][ny]) {
const [tx, ty] = snake[tailIndex];
board[tx][ty] = 0;
tailIndex++;
}
snake.push([nx, ny]);
board[nx][ny] = 1;
direction = (direction + 4 + (rotations[time] ?? 0)) % 4;
}
console.log(time);
큐를 구현하지 않고 인덱스를 활용하여 해결할 수도 있다.
일반 배열에 뱀이 이동할 때마다 계속해서 좌표를 push하고, 빈 칸으로 이동할 때 뱀의 꼬리 칸을 shift하지 않고 그냥 두고 꼬리칸을 가리키는 index만 증가시키는 방식이다.