Skip to content

Commit 5a2a333

Browse files
committed
Added solution to Day 10 part 2
1 parent d9678aa commit 5a2a333

File tree

1 file changed

+53
-29
lines changed

1 file changed

+53
-29
lines changed

day10.py

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
from collections import namedtuple
44
import math
55
from functools import lru_cache
6+
import itertools
67
from operator import itemgetter
7-
from pprint import pprint
88

99
class Vector(namedtuple('Vector', ['x','y'])):
1010
def __add__(self, other):
@@ -27,10 +27,11 @@ def main():
2727
aoc.header("Monitoring Station")
2828
aoc.run_tests()
2929

30-
aoc.output(1, part1)
31-
# aoc.output(2, part2)
30+
(asteroids, edge, station, _) = aoc.output(1, part1, post=itemgetter(3))
31+
aoc.output(2, part2, args=[asteroids, edge, station])
3232

3333
def test():
34+
# part 1
3435
def assert_best(inp : List[str], station : Vector, count : int):
3536
(ast, edge) = to_points(inp)
3637
best = find_best(ast, edge)
@@ -84,7 +85,7 @@ def assert_best(inp : List[str], station : Vector, count : int):
8485
".....#.#.."
8586
], Vector(6,3), 41)
8687

87-
assert_best([
88+
large_example = [
8889
".#..##.###...#######",
8990
"##.############..##.",
9091
".#.######.########.#",
@@ -105,15 +106,42 @@ def assert_best(inp : List[str], station : Vector, count : int):
105106
".#.#.###########.###",
106107
"#.#.#.#####.####.###",
107108
"###.##.####.##.#..##"
108-
], Vector(11,13), 210)
109+
]
110+
assert_best(large_example, Vector(11,13), 210)
111+
112+
# part 2
113+
(ast, edge) = to_points(large_example)
114+
(station, _) = find_best(ast,edge)
115+
ast.remove(station)
116+
117+
vaporized_ordered = list(vaporize(station, rays_sorted(edge), ast, edge))
118+
assert vaporized_ordered[:3] == [Vector(11,12),Vector(12,1),Vector(12,2)]
119+
120+
assert vaporized_ordered[9] == Vector(12,8)
121+
assert vaporized_ordered[19] == Vector(16,0)
122+
assert vaporized_ordered[49] == Vector(16,9)
123+
assert vaporized_ordered[99] == Vector(10,16)
124+
125+
assert vaporized_ordered[198] == Vector(9,6)
126+
assert vaporized_ordered[199] == Vector(8,2)
127+
assert vaporized_ordered[200] == Vector(10,9)
128+
129+
assert vaporized_ordered[298] == Vector(11,1)
130+
assert len(vaporized_ordered) == 299
131+
132+
assert next(itertools.islice(vaporized_ordered, 199, None)) == Vector(8,2)
133+
109134

110135
def part1():
111136
(asteroids, edge) = to_points(aoc.get_input().readlines())
112137
best = find_best(asteroids, edge)
113-
return best[1]
138+
return (asteroids, edge, best[0], best[1])
114139

115-
def part2():
116-
pass
140+
def part2(asteroids, edge, station):
141+
asteroids.remove(station)
142+
it = vaporize(station, rays_sorted(edge), asteroids, edge)
143+
v = next(itertools.islice(it, 199, None))
144+
return (v.x * 100) + v.y
117145

118146
def to_points(lines : List[str]) -> Tuple[Set[Vector], Vector]:
119147
edge = Vector(len(lines[-1]) - 1, len(lines) - 1)
@@ -135,20 +163,6 @@ def edges(edge : Vector):
135163
def in_field(test : Vector, edge : Vector):
136164
return 0<=test.x<=edge.x and 0<=test.y<=edge.y
137165

138-
def rays(origin : Vector, edge : Vector, edge_vectors):
139-
# This is problematic
140-
# Consider a ray of normalised length
141-
# where 1 step from the origin is before the edge,
142-
# and two steps from the origin is after the edge
143-
# It will never be generated
144-
rays = set()
145-
for e in map(lambda e: e - origin, edge_vectors):
146-
if (g := math.gcd(e.x,e.y)) > 1:
147-
rays.add(Vector(e.x//g, e.y//g))
148-
elif g > 0:
149-
rays.add(e)
150-
return rays
151-
152166
@lru_cache
153167
def rays_fixed(edge : Vector):
154168
def it(origin : Vector):
@@ -164,25 +178,36 @@ def it(origin : Vector):
164178
rays.update(it(Vector( edge.x, edge.y )))
165179
return rays
166180

181+
@lru_cache
182+
def rays_sorted(edge : Vector):
183+
rays = rays_fixed(edge)
184+
return list(sorted(rays, key=lambda V:math.atan2(V.x, V.y), reverse=True))
185+
167186
def trace(origin : Vector, rays: Set[Vector], asteroids : Set[Vector], edge : Vector) -> Set[Vector]:
168187
for ray in rays:
169-
# print(f" Tracing along {ray}", end="", flush=True)
170188
p = origin + ray
171189
while in_field(p, edge):
172-
# print(".", end="", flush=True)
173190
if p in asteroids:
174191
yield p
175-
# print(f"asteroid at {p}")
176192
break
177193
p = p + ray
178-
# print()
194+
195+
def vaporize(origin : Vector, rays_clockwise : List[Vector], asteroids : Set[Vector], edge : Vector):
196+
for ray in itertools.cycle(rays_clockwise):
197+
p = origin + ray
198+
while in_field(p, edge):
199+
if p in asteroids:
200+
yield p
201+
asteroids.remove(p)
202+
break # while in_field, go to next iteration of for
203+
p = p + ray
204+
if len(asteroids) == 0: break
205+
179206

180207
def naive_raytrace(asteroids : Set[Vector], edge : Vector):
181208
r = rays_fixed(edge)
182209

183210
for asteroid in asteroids:
184-
# print(f"Tracing from {asteroid}")
185-
# print(f" Got rays ({len(r)})")
186211
yield asteroid, trace(asteroid, r, asteroids, edge)
187212

188213
def find_best(asteroids : Set[Vector], edge : Vector):
@@ -208,7 +233,6 @@ def print_field(mappings : Dict[str,Set[Vector]], edge : Vector):
208233
for line in field:
209234
print("".join(line))
210235

211-
212236

213237
if __name__ == "__main__":
214238
main()

0 commit comments

Comments
 (0)