Public
Edited
Dec 3, 2022
1 fork
1 star
Insert cell
Insert cell
Insert cell
function encode(row, col) {
return col * 100 + row;
}
Insert cell
function decode(pos) {
return [pos % 100, Math.floor(pos / 100)];
}
Insert cell
function asteroidLocations(grid) {
const [nRows, nCols] = [grid.length, grid[0].length];
const locations = [];
for (let row = 0; row < nRows; row++) {
for (let col = 0; col < nCols; col++) {
if (grid[row][col] === "#") {
locations.push(encode(row, col));
}
}
}
return locations;
}
Insert cell
Insert cell
function otherAsteroids(l0, grid) {
const [r0, c0] = decode(l0);
const fromL0 = (loc) => {
const [r, c] = decode(loc);
return Math.abs(r - r0) + Math.abs(c - c0);
};
return asteroidLocations(grid)
.filter((loc) => loc !== l0)
.sort((a, b) => fromL0(a) - fromL0(b));
}
Insert cell
Insert cell
function blocked(nRows, nCols, pos0, pos1) {
if (pos0 === pos1) {
return [];
}
const [row0, col0] = decode(pos0);
const [row1, col1] = decode(pos1);
const maxDist = Math.max(nRows, nCols);
const hcf = AOC.highestCommonFactor(row1 - row0, col1 - col0);
const dRow = Math.floor((row1 - row0) / hcf);
const dCol = Math.floor((col1 - col0) / hcf);

return AOC.range(1, maxDist)
.map((d) => [row1 + d * dRow, col1 + d * dCol])
.filter(([r, c]) => r >= 0 && r < nRows && c >= 0 && c < nCols)
.map((p) => encode(...p));
}
Insert cell
Insert cell
function directView(pos0, grid) {
const [nRows, nCols] = [grid.length, grid[0].length];
const removeBlocked = (sortedLocations, visible) => {
if (sortedLocations.length === 0) {
return visible;
}
const pos = sortedLocations.shift();
const invisible = blocked(nRows, nCols, pos0, pos);
return removeBlocked(
sortedLocations.filter((p) => !invisible.includes(p)),
[pos, ...visible]
);
};

return removeBlocked(otherAsteroids(pos0, grid), []).reduce((g, pos) => {
const [r, c] = decode(pos);
g[r][c] = "#";
return g;
}, AOC.gInit(nRows, nCols, "."));
}
Insert cell
Insert cell
function mostVisible(input) {
const numVisible = (pos) => {
return directView(pos, input)
.flat()
.filter((c) => c === "#").length;
};
const candidates = asteroidLocations(input).map((pos) => [
pos,
numVisible(pos)
]);
return candidates.sort(([pos1, nv1], [pos2, nv2]) => nv2 - nv1)[0];
}
Insert cell
Insert cell
function part1(input) {
return mostVisible(input)[1];
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function orderdLocations(pos, grid) {
const [r0, c0] = decode(pos);
return otherAsteroids(pos, grid)
.map((p) => {
const [r, c] = decode(p);
return [r - r0, c - c0, -Math.atan2(c - c0, r - r0)];
})
.sort(([r1, c1, a1], [r2, c2, a2]) => a1 - a2)
.map(([r, c, a]) => [r + r0, c + c0]);
}
Insert cell
function part2(input) {
const cannon = mostVisible(input)[0];
return encode(
...orderdLocations(cannon, directView(cannon, input)).slice(199)[0]
);
}
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