JS, spent way too long on this because I was mutating state in a for loop!
const input = require('fs') .readFileSync(0) .toString() const grid = input.split('\n').map(x => x.split('').map(x => x === '#')) const asteroids = (() => { const result = [] for (let y = 0; y < grid.length; ++y) { for (let x = 0; x < grid[0].length; ++x) { const point = { x, y, isAsteroid: grid[y][x] } if (point.isAsteroid) result.push(point) } } return result })() const angle = (x, y) => Math.atan2(x.y - y.y, x.x - y.x) const distance = (x, y) => Math.sqrt((x.x - y.x) ** 2 + (x.y - y.y) ** 2) const modulo = (x, n) => ((x % n) + n) % n const radToDeg = rad => modulo(rad * (180 / Math.PI), 360) const clockwiseDegrees = (x, y) => { const angleRad = angle(y, x) const angleInDegrees = radToDeg(angleRad) const degreesClockwise = modulo(angleInDegrees - 270, 360) return degreesClockwise } const descend = fn => (a, b) => { var aa = fn(a) var bb = fn(b) return aa > bb ? -1 : aa < bb ? 1 : 0 } const ascend = fn => (a, b) => { var aa = fn(a) var bb = fn(b) return aa < bb ? -1 : aa > bb ? 1 : 0 } function part1(asteroids) { const uniqueAsteroidDistances = asteroids.map(point => { const otherAsteroids = asteroids.filter(x => x !== point) const visibleCount = new Set(otherAsteroids.map(x => angle(point, x))).size return { point, visibleCount } }) const maxAsteroids = uniqueAsteroidDistances.reduce( (p, v) => (p.visibleCount > v.visibleCount ? p : v), { visibleCount: 0 } ) return maxAsteroids } function part2(asteroids, laserLocation, indexToFind) { const angles = asteroids .filter(x => x !== laserLocation) .map(p => { const angleDeg = clockwiseDegrees(laserLocation, p) return { angle: angleDeg, distance: distance(laserLocation, p), point: p } }) .sort(ascend(p => p.angle)) const grouped = angles .reduce((p, v) => { if (p.length === 0) { p[0] = [v] } else if (p[p.length - 1][0].angle === v.angle) { p[p.length - 1].push(v) } else { p.push([v]) } return p }, []) .map(x => x.slice().sort(descend(x => x.distance))) const order = [] for (let i = 0; i < angles.length; ++i) { const value = grouped[i % grouped.length].pop() if (value) order.push(value) } const toFind = order[indexToFind - 1] return toFind.point.x * 100 + toFind.point.y } const part1Answer = part1(asteroids) console.log(part1Answer.visibleCount) console.log(part2(asteroids, part1Answer.point, 200))
Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink.
Hide child comments as well
Confirm
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
JS, spent way too long on this because I was mutating state in a for loop!