Skip to content

Instantly share code, notes, and snippets.

@FelicitusNeko
Last active December 17, 2019 22:10
Show Gist options
  • Select an option

  • Save FelicitusNeko/8339ff654f41eb9578d3442dca346a69 to your computer and use it in GitHub Desktop.

Select an option

Save FelicitusNeko/8339ff654f41eb9578d3442dca346a69 to your computer and use it in GitHub Desktop.
Advent of Code 2019 Day 10
class Point {
constructor(x, y) {
this.X = x; this.Y = y;
}
distanceTo(rhs) {
if (!(rhs instanceof Point)) throw new Error('Parameter is not a Point');
return Math.abs(Math.sqrt(Math.pow(rhs.Y - this.Y, 2) + Math.pow(rhs.X - this.X, 2)));
}
angleTo(rhs) {
if (!(rhs instanceof Point)) throw new Error('Parameter is not a Point');
return Math.round(Math.atan2(rhs.Y - this.Y, rhs.X - this.X) / Math.PI * 18000) / 100;
}
isAt(x, y) { return x == this.X && y == this.Y; }
}
const mapCalc = data => {
let map = data.split(/[\r\n]+/).map(i => i.split(''));
let asteroids = [];
for (let y in map) for (let x in map[y]) {
x = parseInt(x); y = parseInt(y);
if (map[y][x] === '#') asteroids.push(new Point(x, y));
}
const scan = (target) => {
let scanData = { asteroids: 0, asterData: [] };
for (let asteRead of asteroids) {
if (target.isAt(asteRead.X, asteRead.Y)) continue;
let angle = target.angleTo(asteRead);
if (!scanData.asterData.includes(angle)) {
scanData.asteroids++;
scanData.asterData.push(angle);
}
}
return scanData;
}
let bestResult = { point: [], asteroids: -1 };
for (let asteroid of asteroids) {
let result = scan(asteroid);
if (result.asteroids > bestResult.asteroids) bestResult = { point: [ asteroid ], asteroids: result.asteroids };
else if (result.asteroids === bestResult.asteroids) bestResult.point.push(asteroid);
}
return bestResult;
}
[
[ `.#..#
.....
#####
....#
...##`, 3, 4, 8 ],
[ `......#.#.
#..#.#....
..#######.
.#.#.###..
.#..#.....
..#....#.#
#..#....#.
.##.#..###
##...#..#.
.#....####`, 5, 8, 33 ],
[ `#.#...#.#.
.###....#.
.#....#...
##.#.#.#.#
....#.#.#.
.##..###.#
..#...##..
..##....##
......#...
.####.###.`, 1, 2, 35 ],
[ `.#..#..###
####.###.#
....###.#.
..###.##.#
##.##.#.#.
....###..#
..#.#..#.#
#..#.#.###
.##...##.#
.....#.#..`, 6, 3, 41 ],
[ `.#..##.###...#######
##.############..##.
.#.######.########.#
.###.#######.####.#.
#####.##.#.##.###.##
..#####..#.#########
####################
#.####....###.#.#.##
##.#################
#####.##.###..####..
..######..##.#######
####.##.####...##..#
.#####..#.######.###
##...#.##########...
#.##########.#######
.####.#.###.###.#.##
....##.##.###..#####
.#.#.###########.###
#.#.#.#####.####.###
###.##.####.##.#..##`, 11, 13, 210 ]
].forEach((i,x) => {
let { asteroids, point } = mapCalc(i[0]);
console.assert(asteroids === i[3] && point.reduce((r,ii) => r || ii.isAt(i[1], i[2]), false), `Fail test #${x} (expected ${i[3]} asteroid(s) at ${i[1]},${i[2]}, got ${asteroids} at ${point})`);
});
let bigData = `##.#..#..###.####...######
#..#####...###.###..#.###.
..#.#####....####.#.#...##
.##..#.#....##..##.#.#....
#.####...#.###..#.##.#..#.
..#..#.#######.####...#.##
#...####.#...#.#####..#.#.
.#..#.##.#....########..##
......##.####.#.##....####
.##.#....#####.####.#.####
..#.#.#.#....#....##.#....
....#######..#.##.#.##.###
###.#######.#..#########..
###.#.#..#....#..#.##..##.
#####.#..#.#..###.#.##.###
.#####.#####....#..###...#
##.#.......###.##.#.##....
...#.#.#.###.#.#..##..####
#....#####.##.###...####.#
#.##.#.######.##..#####.##
#.###.##..##.##.#.###..###
#.####..######...#...#####
#..#..########.#.#...#..##
.##..#.####....#..#..#....
.###.##..#####...###.#.#.#
.##..######...###..#####.#`;
console.log(mapCalc(bigData));
class Point {
constructor(x, y) {
this.X = x; this.Y = y;
}
distanceTo(rhs) {
if (!(rhs instanceof Point)) throw new Error('Parameter is not a Point');
return Math.abs(Math.sqrt(Math.pow(rhs.Y - this.Y, 2) + Math.pow(rhs.X - this.X, 2)));
}
angleTo(rhs) {
if (!(rhs instanceof Point)) throw new Error('Parameter is not a Point');
let retval = Math.round(Math.atan2(rhs.Y - this.Y, rhs.X - this.X) / Math.PI * 18000 + 9000) / 100;
if (retval < 0) retval += 360;
return retval;
}
isAt(x, y) { return x == this.X && y == this.Y; }
}
const genMap = data => {
let map = data.split(/[\r\n]+/).map(i => i.split(''));
let asteroids = [];
for (let y in map) for (let x in map[y]) {
x = parseInt(x); y = parseInt(y);
if (map[y][x] === '#') asteroids.push(new Point(x, y));
}
return { map, asteroids };
}
const mapCalc = data => {
const { map, asteroids } = genMap(data);
const scan = (target) => {
let scanData = { asteroids: 0, asterData: [] };
for (let asteRead of asteroids) {
if (target.isAt(asteRead.X, asteRead.Y)) continue;
let angle = target.angleTo(asteRead);
if (!scanData.asterData.includes(angle)) {
scanData.asteroids++;
scanData.asterData.push(angle);
}
}
return scanData;
}
let bestResult = { point: [], asteroids: -1 };
for (let asteroid of asteroids) {
let result = scan(asteroid);
if (result.asteroids > bestResult.asteroids) bestResult = { point: [asteroid], asteroids: result.asteroids };
else if (result.asteroids === bestResult.asteroids) bestResult.point.push(asteroid);
}
return bestResult;
}
const zapCalc = (data, target) => {
const { map, asteroids } = genMap(data);
let compileData = {};
let killOrder = [];
asteroids.forEach(i => {
if (target.isAt(i.X, i.Y)) return;
let angle = target.angleTo(i), dist = target.distanceTo(i);
if (compileData[angle] === undefined) compileData[angle] = [];
compileData[angle].push({ point: i, dist });
});
let sortedAngles = Object.keys(compileData).map(i => parseFloat(i)).sort((a, b) => {
if (a < b) return -1;
else if (a > b) return 1;
else return 0;
});
for (let angle in compileData) {
compileData[angle].sort((a, b) => {
if (a.dist < b.dist) return -1;
else if (a.dist > b.dist) return 1;
else return 0;
});
}
while (asteroids.length > killOrder.length + 1) for (let angle of sortedAngles) {
let boom = compileData[angle].shift();
if (boom === undefined) continue;
killOrder.push(boom.point);
}
return killOrder;
}
[
[`.#..##.###...#######
##.############..##.
.#.######.########.#
.###.#######.####.#.
#####.##.#.##.###.##
..#####..#.#########
####################
#.####....###.#.#.##
##.#################
#####.##.###..####..
..######..##.#######
####.##.####...##..#
.#####..#.######.###
##...#.##########...
#.##########.#######
.####.#.###.###.#.##
....##.##.###..#####
.#.#.###########.###
#.#.#.#####.####.###
###.##.####.##.#..##`, 11, 13, 210, 8, 2]
].forEach((i, x) => {
let { asteroids, point } = mapCalc(i[0]);
console.assert(asteroids === i[3] && point.reduce((r, ii) => r || ii.isAt(i[1], i[2]), false), `Fail test #${x}.1 (expected ${i[3]} asteroid(s) at ${i[1]},${i[2]}, got ${asteroids} at ${point})`);
console.assert(zapCalc(i[0], new Point(i[1], i[2]))[199].isAt(i[4], i[5]), `Fail test #${x}.2`);
});
let bigData = `##.#..#..###.####...######
#..#####...###.###..#.###.
..#.#####....####.#.#...##
.##..#.#....##..##.#.#....
#.####...#.###..#.##.#..#.
..#..#.#######.####...#.##
#...####.#...#.#####..#.#.
.#..#.##.#....########..##
......##.####.#.##....####
.##.#....#####.####.#.####
..#.#.#.#....#....##.#....
....#######..#.##.#.##.###
###.#######.#..#########..
###.#.#..#....#..#.##..##.
#####.#..#.#..###.#.##.###
.#####.#####....#..###...#
##.#.......###.##.#.##....
...#.#.#.###.#.#..##..####
#....#####.##.###...####.#
#.##.#.######.##..#####.##
#.###.##..##.##.#.###..###
#.####..######...#...#####
#..#..########.#.#...#..##
.##..#.####....#..#..#....
.###.##..#####...###.#.#.#
.##..######...###..#####.#`;
console.log(zapCalc(bigData, mapCalc(bigData).point[0])[199]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment