Super messy 2019 day 10

I accidentally inverted my y-axis and I'm not fixing it.
This commit is contained in:
2021-01-24 13:54:48 +01:00
parent 2907726363
commit dd039e9276
2 changed files with 179 additions and 0 deletions

93
2019/aoc2019/day10.py Normal file
View File

@@ -0,0 +1,93 @@
import math
from collections import defaultdict
from typing import TextIO, Tuple
import numpy # type: ignore
def read_asteroids(data: TextIO) -> Tuple[numpy.array, numpy.array]:
xs = []
ys = []
for y, line in enumerate(data):
for x, c in enumerate(line):
if c == '#':
xs.append(x)
ys.append(y)
return numpy.array(xs), -numpy.array(ys)
def asteroids_visible(x: int, y: int, xs: numpy.array, ys: numpy.array) -> int:
dx = xs - x
dy = ys - y
div = numpy.abs(numpy.gcd(dx, dy))
mask = div != 0
dx[mask] //= div[mask]
dy[mask] //= div[mask]
unique = set(zip(dx, dy))
return len(unique) - 1 # need to ignore the point itself
def part1(data: TextIO) -> int:
xs, ys = read_asteroids(data)
return max(asteroids_visible(x, y, xs, ys) for x, y in zip(xs, ys))
def part2(data: TextIO) -> int:
xs, ys = read_asteroids(data)
cx, cy = max(zip(xs, ys), key=lambda c: asteroids_visible(c[0], c[1], xs, ys))
dx = xs - cx
dy = ys - cy
angles = numpy.arctan2(dy, dx)
distances = numpy.abs(numpy.copy(dx)) + numpy.abs(numpy.copy(dy))
to_shoot = defaultdict(list)
for angle, distance, dx, dy in zip(angles, distances, dx, dy):
if distance == 0:
# The point itself
continue
to_shoot[angle].append((distance, dx, dy))
for distances in to_shoot.values():
distances.sort(reverse=True)
unique_angles = sorted(set(angles), reverse=True)
shot = 0
# First shoot from up clockwise
for angle in unique_angles:
if angle > math.pi / 2:
continue
shot += 1
_, dx, dy = to_shoot[angle].pop()
# Repeatedly shoot until you reach #200
while True:
for angle in unique_angles:
if not to_shoot[angle]:
# Nothing left to shoot
continue
shot += 1
_, dx, dy = to_shoot[angle].pop()
if shot == 200:
x = cx + dx
y = -(cy + dy)
return 100 * x + y

86
2019/tests/test_day10.py Normal file
View File

@@ -0,0 +1,86 @@
from io import StringIO
from textwrap import dedent
import pytest
from aoc2019.day10 import part1, part2
LARGE_SAMPLE = """\
.#..##.###...#######
##.############..##.
.#.######.########.#
.###.#######.####.#.
#####.##.#.##.###.##
..#####..#.#########
####################
#.####....###.#.#.##
##.#################
#####.##.###..####..
..######..##.#######
####.##.####...##..#
.#####..#.######.###
##...#.##########...
#.##########.#######
.####.#.###.###.#.##
....##.##.###..#####
.#.#.###########.###
#.#.#.#####.####.###
###.##.####.##.#..##
"""
@pytest.mark.parametrize('visible,field', [
(8, dedent("""\
.#..#
.....
#####
....#
...##
""")),
(33, dedent("""\
......#.#.
#..#.#....
..#######.
.#.#.###..
.#..#.....
..#....#.#
#..#....#.
.##.#..###
##...#..#.
.#....####
""")),
(35, dedent("""\
#.#...#.#.
.###....#.
.#....#...
##.#.#.#.#
....#.#.#.
.##..###.#
..#...##..
..##....##
......#...
.####.###.
""")),
(41, dedent("""\
.#..#..###
####.###.#
....###.#.
..###.##.#
##.##.#.#.
....###..#
..#.#..#.#
#..#.#.###
.##...##.#
.....#.#..
""")),
(210, LARGE_SAMPLE),
])
def test_samples_part1(visible: int, field: str) -> None:
data = StringIO(field.strip())
assert part1(data) == visible
def test_samples_part2():
data = StringIO(LARGE_SAMPLE.strip())
assert part2(data) == 802