| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- Array.prototype.count = function(fnc) {
- return this.reduce((total, i, index) => fnc(i, index) ? total+1 : total, 0);
- }
- Array.prototype.countUnique = function(fnc) {
- return this.reduce((total, i, index) => (total.indexOf(i) === -1 && fnc(i, index)) ? total.concat(i):total, []).length;
- }
- const COLOR_RESET = '\x1B[39m';
- const CLEAR_SCR = '\033[2J';
- const COLOR_MAP = [ '\033[31m', '\033[32m', '\033[33m', '\033[35m', '\033[36m' ];
- const chars = ['@', '!', '$', '%', '+', '=', '?', '#'];
- function Elf(px, py) {
- this.px = px;
- this.py = py;
- this.nextX = 0;
- this.nextY = 0;
- this.moveList = [
- {
- cond: (surrounding) => !surrounding[0][0] && !surrounding[1][0] && !surrounding[2][0],
- action: (self) => { self.nextX = self.px; self.nextY = self.py -1; }
- },
- {
- cond: (surrounding) => !surrounding[0][2] && !surrounding[1][2] && !surrounding[2][2],
- action: (self) => { self.nextX = self.px; self.nextY = self.py +1; }
- },
- {
- cond: (surrounding) => !surrounding[0][0] && !surrounding[0][1] && !surrounding[0][2],
- action: (self) => { self.nextX = self.px -1; self.nextY = self.py; }
- },
- {
- cond: (surrounding) => !surrounding[2][0] && !surrounding[2][1] && !surrounding[2][2],
- action: (self) => { self.nextX = self.px +1; self.nextY = self.py; }
- }
- ];
- this.color = COLOR_MAP[Math.floor(Math.random() * COLOR_MAP.length)];
- this.c = chars[Math.floor(Math.random() * chars.length)];
- this.done = false;
- }
- Elf.prototype.round = function(pool, roundId) {
- const surrounding = pool.surround(this.px, this.py);
- if (surrounding._count === 0) {
- this.nextX = this.px;
- this.nextY = this.py;
- } else for (let i =0; i < 4; ++i) {
- if (this.moveList[(i + roundId) % this.moveList.length].cond(surrounding)) {
- this.moveList[(i + roundId) % this.moveList.length].action(this);
- return;
- }
- }
- this.nextX = this.px;
- this.nextY = this.py;
- }
- function ElfPool() {
- this.elves = [];
- this.boundaries = [[Infinity, -Infinity], [Infinity, -Infinity]];
- }
- ElfPool.prototype.dopush = function(px, py) {
- this.elves.push(new Elf(px, py));
- this.boundaries = [
- [Math.min(this.boundaries[0][0], px), Math.max(this.boundaries[0][1], px)],
- [Math.min(this.boundaries[1][0], py), Math.max(this.boundaries[1][1], py)]];
- }
- ElfPool.prototype.round = function(roundId) {
- for (let i of this.elves)
- i.round(this, roundId);
- if (this.elves.every(x => x.px === x.nextX && x.py === x.nextY)) return true;
- this.elves.forEach(i => i.done = false);
- this.boundaries = [[Infinity, -Infinity], [Infinity, -Infinity]];
- for (let i =0; i < this.elves.length; ++i) {
- if (!this.elves[i].done)
- for (let j =i +1; j < this.elves.length; ++j) {
- if (this.elves[i].nextX === this.elves[j].nextX &&
- this.elves[i].nextY === this.elves[j].nextY)
- this.elves[i].done = this.elves[j].done = true;
- }
- if (!this.elves[i].done) {
- this.elves[i].px = this.elves[i].nextX;
- this.elves[i].py = this.elves[i].nextY;
- this.boundaries = [
- [Math.min(this.boundaries[0][0], this.elves[i].px), Math.max(this.boundaries[0][1], this.elves[i].px)],
- [Math.min(this.boundaries[1][0], this.elves[i].py), Math.max(this.boundaries[1][1], this.elves[i].py)]];
- }
- }
- return false;
- }
- ElfPool.prototype.surround = function(px, py) {
- let result = [ [ false, false, false], [ false, false, false ], [ false, false, false ]];
- result._count = 0;
- for (let i = px-1; i <= px+1; ++i)
- for (let j=py -1; j <= py +1; ++j)
- if ((i !== px || j !== py) && this.elves.some(x => x.py === j && x.px === i)) {
- result[i-px+1][j-py+1] = true;
- result._count++;
- }
- return result;
- }
- ElfPool.prototype.display = async function() {
- let minY = this.boundaries[1][0];
- let minX = this.boundaries[0][0];
- let maxX = this.boundaries[0][1];
- let elvesRows = [];
- console.log(CLEAR_SCR);
- for (let i of this.elves) {
- if (!elvesRows[i.py - minY])
- elvesRows[i.py - minY] = [];
- elvesRows[i.py - minY].push({x: i.px, color: i.color, c: i.c });
- }
- for (let i =0; i < elvesRows.length; ++i) {
- _i = (elvesRows[i] || []).sort((a, b) => a.x-b.x);
- let line = '';
- for (let pos = minX; pos <= maxX; ++pos) {
- if (_i[0]?.x === pos) {
- line += _i[0].color+_i[0].c+COLOR_RESET;
- _i.shift();
- } else {
- line += '.';
- }
- }
- console.log(line);
- }
- return new Promise((ok, ko) => setTimeout(ok, 450));
- }
- let _main = (async()=>{
- let pool = new ElfPool();
- let lineIndex = 0;
- for await (let line of require('readline').createInterface({ input: process.stdin })) {
- for (let i =0; i < line.length; ++i)
- if (line[i] === '#')
- pool.dopush(i, lineIndex);
- ++lineIndex;
- }
- let i =0;
- let part1Solution = 0;
- while (true) {
- if (i === 10)
- part1Solution = ((pool.boundaries[0][1]-pool.boundaries[0][0]+1) * (pool.boundaries[1][1]-pool.boundaries[1][0]+1)) - pool.elves.length;
- if (pool.round(i))
- break;
- ++i;
- await pool.display();
- }
- await pool.display();
- console.log("Part 1: ", part1Solution);
- console.log("Part 2: ", ++i);
- });
- // response < 4241
- // > 4076
- _main();
|