Public
Edited
Dec 12
Paused
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function parse(input) {
return input.split("\n").map((d) => d.split(""));
}
Insert cell
Insert cell
function traverse(r, c, grid, visited, fn, id = true) {
const [nRows, nCols] = [grid.length, grid[0].length];
const z = grid[r][c];
visited[r][c] = id;

return (
fn(r, c, grid) +
(r > 0 && grid[r - 1][c] === z && !visited[r - 1][c]
? traverse(r - 1, c, grid, visited, fn, id)
: 0) +
(c > 0 && grid[r][c - 1] === z && !visited[r][c - 1]
? traverse(r, c - 1, grid, visited, fn, id)
: 0) +
(r < nRows - 1 && grid[r + 1][c] === z && !visited[r + 1][c]
? traverse(r + 1, c, grid, visited, fn, id)
: 0) +
(c < nCols - 1 && grid[r][c + 1] === z && !visited[r][c + 1]
? traverse(r, c + 1, grid, visited, fn, id)
: 0)
);
}
Insert cell
Insert cell
function createParcels(grid) {
const [nRows, nCols] = [grid.length, grid[0].length];
const idGrid = AOC.gInit(nRows, nCols, false);
const parcels = [];
let id = 1;

// First pass to create parcels with area measurements
for (let r = 0; r < nRows; r++) {
for (let c = 0; c < nCols; c++) {
if (!idGrid[r][c]) {
idGrid[r][c] = id;
const area = traverse(r, c, grid, idGrid, () => 1, id);
parcels.push({ id, r, c, area });
id++;
}
}
}
return { grid: idGrid, parcels };
}
Insert cell
Insert cell
function cellPerim(r, c, grid) {
const [nRows, nCols] = [grid.length, grid[0].length];
let perim = 0;
if (r === 0 || grid[r - 1][c] !== grid[r][c]) {
perim++;
}
if (c === 0 || grid[r][c - 1] !== grid[r][c]) {
perim++;
}
if (r === nRows - 1 || grid[r + 1][c] !== grid[r][c]) {
perim++;
}
if (c === nCols - 1 || grid[r][c + 1] !== grid[r][c]) {
perim++;
}
return perim;
}
Insert cell
Insert cell
function part1(input) {
const { grid, parcels } = createParcels(parse(input));
const [nRows, nCols] = [grid.length, grid[0].length];
const visited = AOC.gInit(nRows, nCols, false);
parcels.forEach((parcel) => {
parcel.perim = traverse(parcel.r, parcel.c, grid, visited, cellPerim);
});

return d3.sum(parcels, (d) => d.area * d.perim);
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
cornerWindows = [
[
[0, -1],
[-1, -1],
[-1, 0]
],
[
[-1, 0],
[-1, 1],
[0, 1]
],
[
[0, 1],
[1, 1],
[1, 0]
],
[
[1, 0],
[1, -1],
[0, -1]
]
]
Insert cell
Insert cell
function cellCorners(r, c, grid) {
const [nRows, nCols] = [grid.length, grid[0].length];
const isCorner = (r, c, w) => {
const neighbours = w.map(([dr, dc]) =>
r + dr >= 0 &&
c + dc >= 0 &&
r + dr < nRows &&
c + dc < nCols &&
grid[r + dr][c + dc] === grid[r][c]
? 1
: 0
);
return d3.sum(neighbours) === 0
? 3
: d3.sum(neighbours) == 1 && neighbours[1] === 1
? 3
: d3.sum(neighbours) == 2
? 1
: 0;
};

return d3.sum(cornerWindows.map((w) => isCorner(r, c, w))) / 3;
}
Insert cell
function part2(input) {
const { grid, parcels } = createParcels(parse(input));
const [nRows, nCols] = [grid.length, grid[0].length];
const visited = AOC.gInit(nRows, nCols, false);
parcels.forEach((parcel) => {
parcel.edges = traverse(parcel.r, parcel.c, grid, visited, cellCorners);
});

return d3.sum(parcels, (d) => d.area * d.edges);
}
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