Public
Edited
Dec 3, 2023
Insert cell
Insert cell
Insert cell
function parse(input) {
return input.split("\n").map((row) => row.split(""));
}
Insert cell
Insert cell
function isSymbol(grid, r, c) {
return grid[r][c] !== "." && isNaN(grid[r][c]);
}
Insert cell
Insert cell
function getNumber(grid, r, c) {
let start = c;
while (start > 0 && !isNaN(grid[r][start - 1])) {
start--;
}
let digits = "";
for (let i = start; i < grid[r].length && !isNaN(grid[r][i]); i++) {
digits += grid[r][i];
}
return [r, start, Number(digits)];
}
Insert cell
Insert cell
offsets = [
[-1, -1],
[-1, 0],
[-1, 1],
[0, -1],
[0, 1],
[1, -1],
[1, 0],
[1, 1]
]
Insert cell
Insert cell
function hasAdjacentSymbol(grid, r, c) {
for (const [dr, dc] of offsets) {
const [nr, nc] = [r + dr, c + dc];
if (grid[nr]?.[nc] !== undefined && isSymbol(grid, nr, nc)) {
return true;
}
}
return false;
}
Insert cell
function symbolAdjacentNumberTotal(grid) {
const nums = new Set();
let numTotal = 0;

grid.forEach((row, r) => {
row.forEach((cell, c) => {
if (!isNaN(cell) && hasAdjacentSymbol(grid, r, c)) {
const [numRow, numCol, num] = getNumber(grid, r, c);
const numHash = `${numRow},${numCol}`;
if (!nums.has(numHash)) {
nums.add(numHash);
numTotal += num;
}
}
});
});
return numTotal;
}
Insert cell
function part1(input) {
return symbolAdjacentNumberTotal(parse(input));
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function adjacentNumbers(grid, r, c) {
const [nRows, nCols] = [grid.length, grid[0].length];
const hashes = new Set();
const hash = ([row, left, num]) => `${row},${left},${num}`;

for (const [dr, dc] of offsets) {
const [nr, nc] = [r + dr, c + dc];
const cell = grid[nr]?.[nc];
if (cell !== undefined && !isNaN(cell)) {
hashes.add(hash(getNumber(grid, nr, nc)));
}
}
return hashes;
}
Insert cell
Insert cell
function isGear(grid, r, c) {
return grid[r][c] === "*";
}
Insert cell
Insert cell
function gearRatios(grid) {
let ratioTotal = 0;
grid.forEach((row, r) => {
row.forEach((cell, c) => {
if (isGear(grid, r, c)) {
const adjNums = adjacentNumbers(grid, r, c);
if (adjNums.size === 2) {
ratioTotal += AOC.product(
[...adjNums].map((s) => Number(s.split(",")[2]))
);
}
}
});
});
return ratioTotal;
}

Insert cell
function part2(input) {
return gearRatios(parse(input));
}
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