Day 23
This commit is contained in:
parent
8efeb39931
commit
b107ee7053
71
23/input
Normal file
71
23/input
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#.##..##.#..#.##..##....##..#..#####...#.###.#..##..#..#.#...##..##....
|
||||||
|
##..###.#.#.#..##.##.####.........#...#..#..#.#..#.#....##..###.#.##..#
|
||||||
|
#.......###....#.#.##.#.#.#.##..###...###..##.....#...#.##.##.......##.
|
||||||
|
...##.#......#.#.#..#.###..#.###....#....#.###.##....####....##....##..
|
||||||
|
.#...##..###...##.#.#..#...####.#.##.#.#..#.##.###.###.#.##.##..#.#...#
|
||||||
|
#..##....##.#..##.##...###..##.#...##...#####...#####.##..#.###....#.#.
|
||||||
|
###....#....#.##.####.###.#..####..##..##..#..#.##.#######.##....###...
|
||||||
|
###..###.....###..##..##....#......#.#.##...####.######..###.###....###
|
||||||
|
#.#.###.###.....###.####.#.####...#.#.###.#...#.##..##.##.#..####..#...
|
||||||
|
####.##...#....##.##.#.#....##.###....#.#..#.....##...##.#...###.##.#.#
|
||||||
|
...#.#..####.###...###.#....###...##.####..#.######.##.##..#.#..##...#.
|
||||||
|
#####......#.####.#####...#...#..#..#.#.#.#.#.#.#.#.##.#..#.###.#....#.
|
||||||
|
#..#.#.#..#...#.#.##..#.######.##..#.###...#.#.#...#.####..##..##..#.#.
|
||||||
|
..#.#..###....#.##.##....####.#########..#.########..##....#..#..##..#.
|
||||||
|
.#.#.#...##...##.#.#..#..#####..###....#..#...####.##.####.###.##..##..
|
||||||
|
.##.####..#.#######..#.#######..##..###....#.#..#..##.#..#.#..###.....#
|
||||||
|
#....#.#####..#.##...###.###....#.#.#.#..#.##.####...#...##..#####.##..
|
||||||
|
...##.###.##...#.##.###.#.###....####.....#.##.##.##.###...###.###.#.##
|
||||||
|
..###...#...##....#.###.....##..####..#.###.####..##.###....##.#....##.
|
||||||
|
...#..##..#..##.###.#....###....#..##..#...##.#..##.#.####...##.##..###
|
||||||
|
######.......####..#..#.#####.......#####..#.#..##..#......#.#.#.#####.
|
||||||
|
.#...#..#.##.###..#.#.#..####.#.########.#.###..####.#..#.#..###.#####.
|
||||||
|
...####.#..#..#.##...#.#####.########.##..##....#####.#.##..######.#.##
|
||||||
|
.....#..##.#.....#..#.#.##..######..####.#..#....##.....###.#.#..##..#.
|
||||||
|
..##.##..##.#.#.##...##.##...#..##.....#..#..#.#.#.....#.#.##.###...###
|
||||||
|
##.#..#.#.####.##....#...##.#...#...#..#.##..#...##.....#.#.##.#####...
|
||||||
|
...#..##..##...#..###....#..#.###..####...#.#..##.###.##......###.#.#.#
|
||||||
|
..##.#.#.##..###.....#..##.#....#....#....#.##..#.#.####.#....##..#..##
|
||||||
|
.##..##..#.#.....###..#.#..#.##.#.#.#..#..#.##.#.###...#..#..##.#....##
|
||||||
|
......#...######....###.##..#.###.####.##.##...#.###...####.##..#..#...
|
||||||
|
#..##.#.###.##......####...#.#.##.#.#....##.##..#.#.....####...#..###..
|
||||||
|
..##...#.##..#.....#######.#.#.###.#.##...####..#.#....##.###..##.#.###
|
||||||
|
...####..#..##.########..#####.##..##...#..##..##..#...###.###....#.###
|
||||||
|
.###.#..#.##.#..###.#.##.#.#...#.#.#.##..##.#....###.#..#.....#..##..#.
|
||||||
|
...##.##...#..#.####.....#.##....####.#.###..##...#..#.####...##..##.##
|
||||||
|
###...##....##..##.#...##......#...##.##.#.....##..##.#..#.##......#..#
|
||||||
|
.......#.######...#####....#...#####.#####...##..#..#.#.#..........#.#.
|
||||||
|
#######.#...#.#..#..#..##..#.####..#.##..###..###.##.#...#.#..#.####.##
|
||||||
|
.#..#......#.#....###.#..##..####.#..#.#..##..#####.#....##.#####.#.#.#
|
||||||
|
.#.###.###..#..#.#.#.#..##.#......###.##.#....#######.#..#.#####.....##
|
||||||
|
#.####..###.#..###.#.#...##.##....###.#.#.#.###..#...#...#.##.###...#..
|
||||||
|
#..##..##.##..##....###..######....#.#####.##..#...#....#.#.###.###....
|
||||||
|
#.###..##.##..#.....##...#..#..#####.#.##..##..#.#...#.....##.#..#.##.#
|
||||||
|
##...#...#.##..####..#..#.###....#...#.....#.#.#.###...###...#####.#.##
|
||||||
|
.#.###.....#.#..#.###########.######..#########.##.##..#.#.#...#..##.##
|
||||||
|
##.#################.#.##.##....####.....#..#.#.##.###.##..#..#.##..#.#
|
||||||
|
.##.####.#.#..##.##.#.#..#.###.#..#..#.####....#.###.####.#.#..##..####
|
||||||
|
##....###.#.####.#.#.............##.....###.##.#.###.####...#####.##.#.
|
||||||
|
...##.#.#.#####.####.##.#..##.###.###.####.#.#.....#.#.#...#####..####.
|
||||||
|
######.#....#...#.#.######.#.#....#.##..#..#..#..#.......#..#.##.#.#...
|
||||||
|
...#..#....#.#.#...###.####..##.#.#..#.#.#.####.#..###...###.######...#
|
||||||
|
#.#.###......##...#...##....###......#.###...#...###..#..####..##...#.#
|
||||||
|
#..##.....#........###.##..#.#.#.#.##..#.##.#..###.##.#.####..###.##.#.
|
||||||
|
.##....#..##.###.#.#.#..#..###..#..#####.##....#..#####.#.##..#.##.###.
|
||||||
|
.#.##.###.####.#.#..#.###.###.#.......####.##...#..##.#.##.##..#.###...
|
||||||
|
#.##...#####.#...#.#.##..###.#.##.###########..#...#..#.#.###.#.##..#.#
|
||||||
|
##...#...#.###.#..##..#...##....#...#.#....###.###.#.#..#...#.#.#.#.###
|
||||||
|
#.#.######.##.#....#.....#..##...#.#####...##.##...#..###.#...##.#..##.
|
||||||
|
##.#######.....#....#.###..#..#.###.###..#.....####....#.####..#.....#.
|
||||||
|
#..#..##..##.#.##......#....#.#.....#......#...##.###..#.#.###.......##
|
||||||
|
#..#.#..######.#.......##..#...#....#####.#...#.##...#...###..####.##..
|
||||||
|
.....#.....#.#.##..###.###.##..#.##.##..#.#####..##.##..###..###..#.###
|
||||||
|
...#.###.#.#.#.##...##.##...#..#..#..####.#.##.#...#.#..##.#.#######.##
|
||||||
|
.####.####..#.####...#...#.#..##...##.##..#....#.#.###.###..#####...##.
|
||||||
|
..##.#.###.####.#####...#......#.#.###...###..##.##.###.####.###.#..#.#
|
||||||
|
#.##..####.#.#..#.##..#.##.#.##.#..###.####.#.#.#.##..#.....##.#.#...#.
|
||||||
|
.##...#.#.#####.###.#...###.#......#####.....#.#######.##.#..##...###..
|
||||||
|
##.#.#####......####.####...#####....#..####.#.#.####...####.###.###.##
|
||||||
|
#.#.#.####..##.##.##.#.##.#.#####.##...#....##..##...#.######.....#..##
|
||||||
|
.#.....#...###.#.#.###.#..#...###...##.......####...####.###..#....#...
|
||||||
|
..##.##..#......###...##.....##.#..#...###.##.#.##.##...#.#...#.#..#...
|
200
23/solution.mjs
Normal file
200
23/solution.mjs
Normal file
@ -0,0 +1,200 @@
|
|||||||
|
import { readFileSync } from 'node:fs';
|
||||||
|
|
||||||
|
const input = readFileSync('input', 'utf-8');
|
||||||
|
|
||||||
|
export class InfiniteGrid {
|
||||||
|
constructor() {
|
||||||
|
this.ox = null;
|
||||||
|
this.oy = null;
|
||||||
|
this.rows = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
get height() {
|
||||||
|
return this.rows.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
get width() {
|
||||||
|
return this.rows[0]?.length ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get(x, y) {
|
||||||
|
return this.rows[y - (this.oy ?? y)]?.[x - (this.ox ?? x)];
|
||||||
|
}
|
||||||
|
|
||||||
|
set(x, y, v) {
|
||||||
|
this.expandToFit(x, y);
|
||||||
|
|
||||||
|
const ax = x - this.ox;
|
||||||
|
const ay = y - this.oy;
|
||||||
|
|
||||||
|
this.rows[ay][ax] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
expandToFit(x, y) {
|
||||||
|
if (this.ox === null) this.ox = x;
|
||||||
|
if (this.oy === null) this.oy = y;
|
||||||
|
|
||||||
|
const left = Math.max(0, this.ox - x);
|
||||||
|
const up = Math.max(0, this.oy - y);
|
||||||
|
const right = Math.max(0, (x - this.ox + 1) - this.width);
|
||||||
|
const down = Math.max(0, (y - this.oy + 1) - this.height);
|
||||||
|
|
||||||
|
if (up || right || down || left) {
|
||||||
|
this.rows = [
|
||||||
|
...new Array(up).fill(new Array(this.width + left + right).fill()),
|
||||||
|
...this.rows.map(row =>
|
||||||
|
[...new Array(left), ...row, ...new Array(right)]
|
||||||
|
),
|
||||||
|
...new Array(down).fill(new Array(this.width + left + right).fill())
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ox -= left;
|
||||||
|
this.oy -= up;
|
||||||
|
}
|
||||||
|
|
||||||
|
getBounds() {
|
||||||
|
return {
|
||||||
|
minX: this.ox,
|
||||||
|
maxX: this.ox + (this.rows[0]?.length ?? 1) - 1,
|
||||||
|
minY: this.oy,
|
||||||
|
maxY: this.oy + (this.rows.length || 1) - 1
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
printDefined() {
|
||||||
|
console.log(this.rows
|
||||||
|
.map(row => row
|
||||||
|
.map(cell => cell ? '#' : '.')
|
||||||
|
.join('')
|
||||||
|
)
|
||||||
|
.join('\n')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
countEmpty() {
|
||||||
|
return this.rows.reduce(
|
||||||
|
(total, row) => total + row.reduce(
|
||||||
|
(rowTotal, cell) => rowTotal + Number(!cell),
|
||||||
|
0
|
||||||
|
),
|
||||||
|
0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Elf {
|
||||||
|
constructor(grid) {
|
||||||
|
this.grid = grid;
|
||||||
|
this.pos = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
moveTo(x, y) {
|
||||||
|
if (this.pos) {
|
||||||
|
this.grid.set(...this.pos, undefined);
|
||||||
|
}
|
||||||
|
this.pos = [x, y];
|
||||||
|
this.grid.set(...this.pos, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
proposePosition(directions) {
|
||||||
|
if (!this.pos) throw new Error('Elf is not on the grid');
|
||||||
|
|
||||||
|
const [x, y] = this.pos;
|
||||||
|
const N = this.grid.get(x, y - 1);
|
||||||
|
const NE = this.grid.get(x + 1, y - 1);
|
||||||
|
const E = this.grid.get(x + 1, y);
|
||||||
|
const SE = this.grid.get(x + 1, y + 1);
|
||||||
|
const S = this.grid.get(x, y + 1);
|
||||||
|
const SW = this.grid.get(x - 1, y + 1);
|
||||||
|
const W = this.grid.get(x - 1, y);
|
||||||
|
const NW = this.grid.get(x - 1, y - 1);
|
||||||
|
|
||||||
|
if (!(N || NE || E || SE || S || SW || W || NW)) {
|
||||||
|
// Don't move
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const direction of directions) {
|
||||||
|
if (direction === 'N' && !(NW || N || NE)) {
|
||||||
|
return [x, y - 1];
|
||||||
|
} else if (direction === 'E' && !(NE || E || SE)) {
|
||||||
|
return [x + 1, y];
|
||||||
|
} else if (direction === 'S' && !(SW || S || SE)) {
|
||||||
|
return [x, y + 1];
|
||||||
|
} else if (direction === 'W' && !(NW || W || SW)) {
|
||||||
|
return [x - 1, y];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const elfPositions = input
|
||||||
|
.split('\n')
|
||||||
|
.map(line => line.trim())
|
||||||
|
.filter(line => !!line)
|
||||||
|
.flatMap((line, y) => line
|
||||||
|
.split('')
|
||||||
|
.map((c, x) => {
|
||||||
|
if (c === '#') {
|
||||||
|
return [x, y];
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(coords => !!coords)
|
||||||
|
);
|
||||||
|
|
||||||
|
const grid = new InfiniteGrid();
|
||||||
|
const elves = [];
|
||||||
|
for (const pos of elfPositions) {
|
||||||
|
const elf = new Elf(grid);
|
||||||
|
elves.push(elf);
|
||||||
|
elf.moveTo(...pos);
|
||||||
|
}
|
||||||
|
const directions = ['N', 'S', 'W', 'E'];
|
||||||
|
let round = 0;
|
||||||
|
|
||||||
|
function processRound() {
|
||||||
|
const propositions = elves.flatMap(elf => {
|
||||||
|
const pos = elf.proposePosition(directions);
|
||||||
|
if (!pos) return [];
|
||||||
|
return [{elf, x: pos[0], y: pos[1]}];
|
||||||
|
});
|
||||||
|
|
||||||
|
propositions.sort((p1, p2) => (p1.x - p2.x) || (p1.y - p2.y));
|
||||||
|
const validPropositions = propositions
|
||||||
|
.reduce((groups, proposition) => {
|
||||||
|
if (groups.length) {
|
||||||
|
const lastGroup = groups[groups.length - 1];
|
||||||
|
const {x: lastX, y: lastY} = lastGroup[0];
|
||||||
|
if (proposition.x === lastX && proposition.y === lastY) {
|
||||||
|
lastGroup.push(proposition);
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
groups.push([proposition]);
|
||||||
|
return groups;
|
||||||
|
}, [])
|
||||||
|
.filter(group => group.length === 1)
|
||||||
|
.flat();
|
||||||
|
|
||||||
|
const moved = validPropositions.length;
|
||||||
|
|
||||||
|
for (const proposition of validPropositions) {
|
||||||
|
proposition.elf.moveTo(proposition.x, proposition.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reorder directions
|
||||||
|
directions.push(directions.shift());
|
||||||
|
|
||||||
|
round++;
|
||||||
|
return moved;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
processRound();
|
||||||
|
} while (round <= 10)
|
||||||
|
console.log('The number of empty ground tiles is:', grid.countEmpty());
|
||||||
|
|
||||||
|
while (processRound() !== 0) {};
|
||||||
|
console.log('The number of rounds to completion is:', round);
|
Loading…
Reference in New Issue
Block a user