Public
Edited
Dec 3, 2023
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function parse(input) {
const grid = input.split("\n");
const result = [];
// For each row...
for (let r = 0; r < grid.length; r++) {
// Find all horizontal runs of digits
const matches = grid[r].matchAll(/\d+/g);
for (const match of matches) {
const number = parseInt(match);
const colStart = match.index;
const colEnd = match.index + match[0].length;
// Find the symbol neighbours of each digit
const neighbours = [
...generateNeighbours(grid, colStart, colEnd, r)
].filter((x) => x);
result.push({ number, neighbours });
}
}
return result;
}
Insert cell
Insert cell
function* generateNeighbours(grid, colStart, colEnd, row) {
const isChar = (i, j) => {
if (i < 0 || j < 0 || i >= grid.length || j >= grid.length) {
return false;
}
const char = grid[i][j];
if (char !== "." && isNaN(parseInt(char))) {
return {
char,
rowIndex: i,
colIndex: j
};
}
return null;
};

for (let col = colStart; col < colEnd; col++) {
if (col === colStart) {
yield isChar(row, col - 1);
yield isChar(row - 1, col - 1);
yield isChar(row + 1, col - 1);
}
if (col === colEnd - 1) {
yield isChar(row, col + 1);
yield isChar(row - 1, col + 1);
yield isChar(row + 1, col + 1);
}
yield isChar(row - 1, col);
yield isChar(row + 1, col);
}
}
Insert cell
Insert cell
Insert cell
function part1(input) {
// Filter only numbers that have at least one neighbour
const validNumbers = parse(input).filter(
({ neighbours }) => neighbours.length
);
// Find the part numbers
const partNumbers = validNumbers.map(({ number }) => number);
return _.sum(partNumbers);
}
Insert cell
Insert cell
Insert cell
Insert cell
function part2(input) {
// Filter only numbers that have a * neighbour
const numbersAdjacentToStar = parse(input)
.filter(({ neighbours }) => neighbours.some(({ char }) => char === "*"))
.flatMap(({ number, neighbours }) =>
neighbours.map((entry) => ({ ...entry, number }))
);
// Group them by row index and column index
const groupByStar = _.groupBy(
numbersAdjacentToStar,
({ rowIndex, colIndex }) => [rowIndex, colIndex]
);
// Gears must have exactly two numbers
const gears = _.filter(groupByStar, (star) => star.length === 2);
// Calculate the gear ratio
const gearRatios = gears.map((gear) => gear[0].number * gear[1].number);
return _.sum(gearRatios);
}
Insert cell
Insert cell
Insert cell
input = textarea || select
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