var fs = require('fs');
var input = fs.readFileSync('/dev/stdin').toString().split('\n');
const Node = class {
position;
prev;
next;
constructor(y, x) {
this.position = [y, x];
}
};
const solution = (N, K, applePositions, L, directionInfo) => {
// dy dx: 명령어가 D일 경우 +1, L일 경우 -1하여 다음 dy dx를 구함
const DIRECTION_ORDER = [
[0, 1],
[1, 0],
[0, -1],
[-1, 0],
];
let directionIdx = 0;
// 뱀의 위치 저장 및 초기화
const snake = new Set();
let head = new Node(0, 0);
let tail = head;
snake.add('0,0');
let time = 0;
let isFinish = false;
// 뱀 move 함수
const moveSnake = () => {
const [dy, dx] = DIRECTION_ORDER[directionIdx];
const [currentY, currentX] = head.position;
const [nextY, nextX] = [currentY + dy, currentX + dx];
const newKey = `${nextY},${nextX}`;
if (snake.has(newKey)) return true; // 뱀의 몸에 부딪힌 경우
if (nextY < 0 || nextY >= N || nextX < 0 || nextX >= N) return true; // 벽에 부딪힌 경우
snake.add(newKey);
const newHead = new Node(nextY, nextX);
newHead.prev = head;
head.next = newHead;
head = newHead;
const appleIdx = applePositions.findIndex(
([y, x]) => nextY === y && nextX === x
);
if (appleIdx === -1) {
const [tailY, tailX] = tail.position;
const tailKey = `${tailY},${tailX}`;
snake.delete(tailKey);
tail = tail.next;
tail.prev = null;
} else {
applePositions.splice(appleIdx, 1);
}
return false;
};
// 게임 진행
while (!isFinish) {
if (directionInfo[0] && Number(directionInfo[0][0]) === time) {
const [_, command] = directionInfo.shift();
if (command === 'D') directionIdx = (directionIdx + 1) % 4;
else {
directionIdx--;
if (directionIdx < 0) directionIdx += 4;
}
}
time++;
isFinish = moveSnake();
}
return time;
};
const N = Number(input[0]);
const K = Number(input[1]);
const applePositions = input
.slice(2, 2 + K)
.map((v) => v.split(' ').map((v) => Number(v) - 1));
const L = Number(input[2 + K]);
const directionInfo = input.slice(3 + K).map((v) => v.split(' '));
console.log(solution(N, K, applePositions, L, directionInfo));
풀이 2는 두 번째로 푼 걸로 풀이시간이 56분이나 걸렸다.
함수 단위로 쪼개보려했는데도 생각보다 많이 쪼개지 못해서 디버깅이에 시간을 많이 허비한 느낌..
다음에 풀 때는 더 아름답게 풀어볼 수 있도록 해야 겠다. (코드들이 별로 마음에 안드네..)
const fs = require('fs');
const Node = class {
prev;
next;
position;
constructor(position) {
this.position = position;
}
};
// dxdy: 오른쪽, 아래쪽, 왼쪽, 위쪽 순서
// command가 D일경우 currentDirection += 1;
// command가 L일경우 currentDirection -= 1;
const DIRECTION = [
[0, 1],
[1, 0],
[0, -1],
[-1, 0],
];
const changeCurrentDirection = (currentDirection, command) => {
if (command === 'D') currentDirection = (currentDirection + 1) % 4;
else if (command === 'L')
currentDirection = currentDirection === 0 ? 3 : currentDirection - 1;
return currentDirection;
};
const moveSnake = (snake, head, tail, currentDirection, apples, N) => {
const [dx, dy] = DIRECTION[currentDirection];
const [x, y] = head.position;
const [nextX, nextY] = [x + dx, y + dy];
// board 밖으로 나간 경우
if (nextX < 1 || nextX > N || nextY < 1 || nextY > N) return [true];
// 몸통에 부딪힌 경우
if (snake.has(JSON.stringify([nextX, nextY]))) return [true];
const newHead = new Node([nextX, nextY]);
head.next = newHead;
newHead.prev = head;
head = newHead;
snake.add(JSON.stringify(head.position));
let appleIdx;
if (
(appleIdx = apples.findIndex(
([ax, ay]) => ax === nextX && ay === nextY
)) !== -1
) {
apples.splice(appleIdx, 1);
} else {
snake.delete(JSON.stringify(tail.position));
tail.next.prev = null;
tail = tail.next;
}
return [false, head, tail];
};
const solution = (N, K, apples, L, commands) => {
const snake = new Set();
let head, tail;
head = tail = new Node([1, 1]);
snake.add(JSON.stringify(head.position));
let isGameOver = false;
let time = 0;
let currentDirection = 0;
let commandIdx = 0;
while (!isGameOver) {
if (commands[commandIdx] && time === Number(commands[commandIdx][0])) {
const command = commands[commandIdx][1];
currentDirection = changeCurrentDirection(currentDirection, command);
commandIdx++;
}
[isGameOver, head, tail] = moveSnake(
snake,
head,
tail,
currentDirection,
apples,
N
);
time++;
}
return time;
};
const input = fs.readFileSync('/dev/stdin').toString().trim().split('\n');
const N = Number(input[0]);
const K = Number(input[1]);
const apples = input.slice(2, 2 + K).map((v) => v.split(' ').map(Number));
const L = Number(input[2 + K]);
const commands = input.slice(3 + K).map((v) => v.split(' '));
console.log(solution(N, K, apples, L, commands));