Published
Edited
Dec 10, 2019
Insert cell
Insert cell
{
const field = new Set(asteroids);

const w = width,
h = width;
const svg = d3.select(DOM.svg(w, h));
const x = d3
.scaleLinear()
.domain(d3.extent(field, d => +d.split(',')[0]))
.range([0, w]);
const y = d3
.scaleLinear()
.domain(d3.extent(field, d => +d.split(',')[1]))
.range([0, h]);
svg
.selectAll('circle')
.data([...field], d => d)
.enter()
.append('circle')
.attr('cx', d => x(d.split(',')[0]))
.attr('cy', d => y(d.split(',')[1]))
.attr('r', w / 200)
.attr('fill', d => (d === part1[0] ? 'red' : 'black'));

yield svg.node();

for (const n of path()) {
field.delete(n);
svg
.selectAll('circle')
.data([...field], d => d)
.exit()
.remove();
yield Promises.delay(10, svg.node());
}
}
Insert cell
function* path() {
const ordered = [
...d3
.rollup(
[...asteroids].filter(a => a !== part1[0]),
d => d.sort((a, b) => -distance(a, b)),
d => angle(d, part1[0])
)
.entries()
]
.sort(([a], [b]) => a - b);
const pivot = ordered.findIndex(([a]) => a >= Math.PI / 2);
const rotated = ordered.slice(pivot).concat(ordered.slice(0, pivot));

let output;
do {
output = false;
for (const [a, asteroids] of rotated)
if (asteroids.length) {
yield asteroids.shift();
output = true;
}
} while (output);
}
Insert cell
part2 = [...path()][199]
Insert cell
function distance(a, b) {
const [x0, y0] = a.split(',').map(Number);
const [x1, y1] = b.split(',').map(Number);
return Math.pow(y1 - y0, 2) + Math.pow(x1 - x0, 2);
}
Insert cell
part1 = [...asteroids]
.map(p => [p, anglesFrom(p).size])
.sort((a, b) => b[1] - a[1])[0]
Insert cell
function anglesFrom(p) {
return d3.group([...asteroids].filter(a => a !== p), d => angle(d, p));
}
Insert cell
angle = (a, b) => {
const [x0, y0] = a.split(',').map(Number);
const [x1, y1] = b.split(',').map(Number);
return Math.atan2(y1 - y0, x1 - x0);
}
Insert cell
asteroids = {
const asteroids = new Set();
const grid = input.split('\n').map(r => r.split(''));
for (let y = 0; y < grid.length; y++)
for (let x = 0; x < grid[y].length; x++)
if (grid[y][x] === '#') asteroids.add(String([x, y]));
return asteroids;
}
Insert cell
input = `..............#.#...............#....#....
#.##.......#....#.#..##........#...#......
..#.....#....#..#.#....#.....#.#.##..#..#.
...........##...#...##....#.#.#....#.##..#
....##....#...........#..#....#......#.###
.#...#......#.#.#.#...#....#.##.##......##
#.##....#.....#.....#...####........###...
.####....#.......#...##..#..#......#...#..
...............#...........#..#.#.#.......
........#.........##...#..........#..##...
...#..................#....#....##..#.....
.............#..#.#.........#........#.##.
...#.#....................##..##..........
.....#.#...##..............#...........#..
......#..###.#........#.....#.##.#......#.
#......#.#.....#...........##.#.....#..#.#
.#.............#..#.....##.....###..#..#..
.#...#.....#.....##.#......##....##....#..
.........#.#..##............#..#...#......
..#..##...#.#..#....#..#.#.......#.##.....
#.......#.#....#.#..##.#...#.......#..###.
.#..........#...##.#....#...#.#.........#.
..#.#.......##..#.##..#.......#.###.......
...#....###...#......#..#.....####........
.............#.#..........#....#......#...
#................#..................#.###.
..###.........##...##..##.................
.#.........#.#####..#...##....#...##......
........#.#...#......#.................##.
.##.....#..##.##.#....#....#......#.#....#
.....#...........#.............#.....#....
........#.##.#...#.###.###....#.#......#..
..#...#.......###..#...#.##.....###.....#.
....#.....#..#.....#...#......###...###...
#..##.###...##.....#.....#....#...###..#..
........######.#...............#...#.#...#
...#.....####.##.....##...##..............
###..#......#...............#......#...#..
#..#...#.#........#.#.#...#..#....#.#.####
#..#...#..........##.#.....##........#.#..
........#....#..###..##....#.#.......##..#
.................##............#.......#..`
Insert cell
d3 = require('d3-array@2', 'd3-scale@3', 'd3-selection@1')
Insert cell
Combinatorics = require('js-combinatorics@0.5')
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