| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- const fs = require('fs');
- const readline = require('readline');
- function Rope(len) {
- this.tokens = [];
- this.visited = {'0x0': true};
- this.visitedCoord = [[0, 0]];
- this.boundaries = [[0, 0], [0, 0]];
- this.len = len;
- for (let i =0; i < len +1; ++i)
- this.tokens.push([0, 0]);
- }
- Rope.prototype.applyMove = function(moveArr) {
- this.tokens[0][0] += moveArr[0];
- this.tokens[0][1] += moveArr[1];
- this.boundaries = [
- [ Math.min(this.boundaries[0][0], this.tokens[0][0]), Math.max(this.boundaries[0][1], this.tokens[0][0]) ],
- [ Math.min(this.boundaries[1][0], this.tokens[0][1]), Math.max(this.boundaries[1][1], this.tokens[0][1]) ],
- ];
- for (let i =0; i < this.tokens.length -1; ++i)
- this.checkAndMove(i);
- this.visited[this.tokens[this.tokens.length -1][0] + 'x' +this.tokens[this.tokens.length -1][1]] = true;
- this.visitedCoord.push([this.tokens[this.tokens.length -1][0], this.tokens[this.tokens.length -1][1]]);
- }
- Rope.prototype.checkAndMove = function(headPos) {
- if (Math.abs(this.tokens[headPos][0] - this.tokens[headPos +1][0]) <= 1 &&
- Math.abs(this.tokens[headPos][1] - this.tokens[headPos+1][1]) <= 1)
- return;
- if (this.tokens[headPos +1][1] !== this.tokens[headPos][1])
- this.tokens[headPos +1][1] += (this.tokens[headPos +1][1] < this.tokens[headPos][1]) ? 1 : -1;
- if (this.tokens[headPos +1][0] !== this.tokens[headPos][0])
- this.tokens[headPos +1][0] += (this.tokens[headPos +1][0] < this.tokens[headPos][0]) ? 1 : -1;
- }
- const COLORS = [ '\033[39m', '\033[31m', '\033[32m', '\033[33m', '\033[34m', '\033[35m', '\033[36m' ]
- function showRope(arenaSize, ropeItems) {
- // clear screen
- for (let i =0; i < 5; ++i) console.log();
- // /clear screen
- console.log('\x1Bc');
- let item = ropeItems.shift();
- for (let py =0; py < arenaSize[1]; ++py) {
- let line = '';
- for (let px =0; px < arenaSize[0]; ++px) {
- if (item && item.x === px && item.y === py) {
- line += COLORS[item.color] + item.c + COLORS[0];
- item = ropeItems.shift();
- } else {
- line += '.';
- }
- }
- console.log(line);
- }
- }
- function prepShowRope(arenaSize, arenaShift, replayRope) {
- showRope(arenaSize, replayRope.tokens
- .map((i, index) => { return {
- x: i[0]+arenaShift[0],
- y: i[1]+arenaShift[1],
- c: '#',
- color: index+1 >= COLORS.length ? Math.ceil(Math.random() * (COLORS.length-1)) : (index +1)
- };}).concat(
- replayRope.visitedCoord.map(i => { return {
- x: i[0] + arenaShift[0],
- y: i[1] + arenaShift[1],
- c: '"',
- color: 0
- };})
- )
- .sort((a, b) => {
- if (a.x === b.x && a.y === b.y)
- return a.c === '"' ? 1 : -1;
- if (a.y === b.y)
- return a.x-b.x;
- return a.y-b.y;
- })
- .filter((value, index, self) => self.findIndex(i => i.x === value.x && i.y === value.y) === index));
- }
- function mSleep() {
- return new Promise(ok => setTimeout(ok, 90));
- }
- async function showReplay(rope, actions) {
- let arenaSize = [ rope.boundaries[0][1] - rope.boundaries[0][0] +1, rope.boundaries[1][1] - rope.boundaries[1][0] +1];
- let arenaShift = [ -rope.boundaries[0][0], -rope.boundaries[1][0] ];
- let replayRope = new Rope(rope.len);
- await prepShowRope(arenaSize, arenaShift, replayRope);
- for (let i of actions) {
- await mSleep();
- replayRope.applyMove(i);
- prepShowRope(arenaSize, arenaShift, replayRope);
- }
- }
- async function main() {
- const move = {
- 'U': [0, -1],
- 'D': [0, 1],
- 'L': [-1, 0],
- 'R': [1, 0]
- };
- let tokens = new Rope(1);
- let tokensPart2 = new Rope(10);
- let moveList = [];
- for await (let line of readline.createInterface({ input: process.stdin })) {
- if (!line || !line.length)
- continue;
- let reg = /([UDLR]) (\d+)/.exec(line);
- for (let i =0; i < reg[2]; ++i) {
- moveList.push(move[reg[1]]);
- tokens.applyMove(move[reg[1]]);
- tokensPart2.applyMove(move[reg[1]]);
- }
- }
- await showReplay(tokensPart2, moveList);
- console.log("Part 1: ", Object.keys(tokens.visited).length);
- console.log("Part 2: ", Object.keys(tokensPart2.visited).length);
- };
- (main());
|