Public
Edited
Dec 14, 2024
Paused
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function parse(input) {
const grid = input.split("\n").map((d) => d.split(""));
const [nRows, nCols] = [grid.length, grid[0].length];
const p = grid.flat().indexOf("^");
const [grdRow, grdCol] = [Math.floor(p / nCols), p % nCols];
grid[grdRow][grdCol] = ".";

return { start: [grdRow, grdCol], dir: 0, grid: grid, nRows, nCols };
}
Insert cell
Insert cell
dirs = [
[-1, 0],
[0, 1],
[1, 0],
[0, -1]
]
Insert cell
Insert cell
function guardPositions(lab) {
const positions = [];
let [[row, col], dir] = [lab.start, lab.dir];

while (true) {
positions.push([row, col, dir]);
const [nextR, nextC] = [row + dirs[dir][0], col + dirs[dir][1]];
if (nextR < 0 || nextR >= lab.nRows || nextC < 0 || nextC >= lab.nCols) {
return positions;
}
if (lab.grid[nextR][nextC] === "#") {
dir = (dir + 1) % 4; // Turn right if hitting an obstruction
}
[row, col] = [row + dirs[dir][0], col + dirs[dir][1]];
}
}
Insert cell
Insert cell
function part1(input) {
return new Set(guardPositions(parse(input)).map((d) => (d[0] << 8) | d[1]))
.size;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function hasLoop(lab) {
const positions = new Set();

let [row, col] = lab.start;
let dir = lab.dir;
let turn = false;

while (true) {
if (turn) {
const pos = (row << 16) | (col << 8) | dir;
if (positions.has(pos)) {
return true;
}
positions.add(pos);
}

const [nextR, nextC] = [row + dirs[dir][0], col + dirs[dir][1]];
if (nextR < 0 || nextR >= lab.nRows || nextC < 0 || nextC > lab.nCols) {
return false;
}

if (lab.grid[nextR][nextC] === "#") {
// If we hit an obstruction, turn, but don't move
dir = (dir + 1) % 4;
turn = true;
} else {
turn = false;
row = nextR;
col = nextC;
}
}
}
Insert cell
Insert cell
function numObstructions(lab) {
const route = [
...new Set(guardPositions(lab).map((d) => (d[0] << 8) | d[1]))
].map((d) => [(d >> 8) & 0xff, d & 0xff]);

const loopPos = new Set();

route.forEach((pos) => {
lab.grid[pos[0]][pos[1]] = "#";
if (hasLoop(lab)) {
loopPos.add((pos[0] << 8) | pos[1]);
}
lab.grid[pos[0]][pos[1]] = ".";
});
return loopPos.size;
}
Insert cell
function part2(input) {
return numObstructions(parse(input));
}
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