Public
Edited
Dec 2
Paused
1 fork
3 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function parse(input, gSize = 180) {
const grid = AOC.gInit(gSize, gSize, 0);
const elfGrd = input.split("\n").map((l) => l.split(""));
const mid = Math.floor((gSize - elfGrd.length) / 2);

const elves = [];
for (let r = 0; r < elfGrd.length; r++) {
for (let c = 0; c < elfGrd[0].length; c++) {
if (elfGrd[r][c] === "#") {
grid[r + mid][c + mid] = 1;
elves.push([r + mid, c + mid]);
}
}
}
return [elves, grid];
}
Insert cell
Insert cell
Insert cell
function neighbours(r, c, grid) {
return [
grid[r - 1][c - 1] + grid[r - 1][c] + grid[r - 1][c + 1] > 0,
grid[r + 1][c + 1] + grid[r + 1][c] + grid[r + 1][c - 1] > 0,
grid[r - 1][c - 1] + grid[r][c - 1] + grid[r + 1][c - 1] > 0,
grid[r - 1][c + 1] + grid[r][c + 1] + grid[r + 1][c + 1] > 0
];
}
Insert cell
Insert cell
function round(elves, grid, first) {
const moves = [
[-1, 0],
[1, 0],
[0, -1],
[0, 1]
];
let elvesMoved = 0;

// Find proposed moves
const fTable = new Map();
const nextElves = elves.map(([r, c]) => {
const ns = neighbours(r, c, grid);
const occupiedSides = ns.filter(AOC.identity).length;
if (occupiedSides === 0 || occupiedSides === 4) {
// No neighbours or neighbours on all sides, so stay here
AOC.addToFreqTable(fTable, r + "," + c);
return [r, c];
}
for (let i = first; i < first + 4; i++) {
if (!ns[i % 4]) {
const newPos = AOC.vAdd([r, c], moves[i % 4]);
AOC.addToFreqTable(fTable, newPos[0] + "," + newPos[1]);
return newPos;
}
}
});

// Only move those who don't have a don't have a conflct
for (let i = 0; i < elves.length; i++) {
const [r, c] = elves[i];
const [rNext, cNext] = nextElves[i];
if ((rNext != r || cNext != c) && fTable.get(rNext + "," + cNext) === 1) {
// Only one elf wants this space, so move it
elvesMoved++;
elves[i] = [rNext, cNext];
grid[r][c] = 0;
grid[rNext][cNext] = 1;
}
}
return elvesMoved;
}
Insert cell
Insert cell
function bounds(elves) {
const rows = elves.map(([r, c]) => r);
const cols = elves.map(([r, c]) => c);
return [
[Math.min(...rows), Math.min(...cols)],
[Math.max(...rows), Math.max(...cols)]
];
}
Insert cell
function empty(elves, grid) {
const [[minR, minC], [maxR, maxC]] = bounds(elves);
return (maxR - minR + 1) * (maxC - minC + 1) - AOC.sum(grid.flat().flat());
}
Insert cell
Insert cell
function part1(input) {
const [elves, grid] = parse(input);
for (let i = 0; i < 10; i++) {
round(elves, grid, i % 4);
}
return empty(elves, grid);
}
Insert cell
Insert cell
Insert cell
Insert cell
function part2(input) {
const [elves, grid] = parse(input);
let i = 0;
let elvesMoved;
do {
elvesMoved = round(elves, grid, i % 4);
i++;
} while (elvesMoved !== 0);
return i;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more