Skip to content

Commit d9678aa

Browse files
committed
Added working solution for Day 10 part 1
1 parent 83122ad commit d9678aa

File tree

1 file changed

+122
-41
lines changed

1 file changed

+122
-41
lines changed

day10.py

Lines changed: 122 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
from typing import List, Tuple, Set, Dict
33
from collections import namedtuple
44
import math
5+
from functools import lru_cache
6+
from operator import itemgetter
57
from pprint import pprint
68

79
class Vector(namedtuple('Vector', ['x','y'])):
@@ -13,56 +15,113 @@ def __sub__(self, other):
1315
assert type(other) == Vector
1416
return Vector(self.x-other.x, self.y-other.y)
1517

18+
def __mul__(self, other):
19+
assert type(other) == int
20+
return Vector(self.x * other, self.y * other)
21+
22+
def __floordiv__(self, other):
23+
assert type(other) == int
24+
return Vector(self.x // other, self.y // other)
25+
1626
def main():
1727
aoc.header("Monitoring Station")
1828
aoc.run_tests()
1929

20-
# aoc.output(1, part1)
30+
aoc.output(1, part1)
2131
# aoc.output(2, part2)
2232

2333
def test():
24-
25-
inp1 = [
34+
def assert_best(inp : List[str], station : Vector, count : int):
35+
(ast, edge) = to_points(inp)
36+
best = find_best(ast, edge)
37+
assert best[0] == station
38+
assert count == best[1]
39+
40+
assert_best([
2641
".#..#",
2742
".....",
2843
"#####",
2944
"....#",
3045
"...##"
31-
]
32-
t = to_points(inp1)
33-
print_field({
34-
'#': t[0],
35-
".": t[1]
36-
}, t[2])
37-
38-
print(t[2])
39-
edge_vectors = set(edges(t[2]))
40-
pprint(edge_vectors)
41-
print_field({'+' : edge_vectors}, t[2])
42-
43-
for origin, asteroids in naive_raytrace(t[0],t[1],t[2]):
44-
print_field({
45-
"*": t[0],
46-
"#": asteroids,
47-
".": {origin}
48-
},t[2])
49-
input()
46+
], Vector(3,4), 8)
47+
48+
assert_best([
49+
"......#.#.",
50+
"#..#.#....",
51+
"..#######.",
52+
".#.#.###..",
53+
".#..#.....",
54+
"..#....#.#",
55+
"#..#....#.",
56+
".##.#..###",
57+
"##...#..#.",
58+
".#....####"
59+
], Vector(5,8), 33)
60+
61+
assert_best([
62+
"#.#...#.#.",
63+
".###....#.",
64+
".#....#...",
65+
"##.#.#.#.#",
66+
"....#.#.#.",
67+
".##..###.#",
68+
"..#...##..",
69+
"..##....##",
70+
"......#...",
71+
".####.###."
72+
], Vector(1,2), 35)
73+
74+
assert_best([
75+
".#..#..###",
76+
"####.###.#",
77+
"....###.#.",
78+
"..###.##.#",
79+
"##.##.#.#.",
80+
"....###..#",
81+
"..#.#..#.#",
82+
"#..#.#.###",
83+
".##...##.#",
84+
".....#.#.."
85+
], Vector(6,3), 41)
86+
87+
assert_best([
88+
".#..##.###...#######",
89+
"##.############..##.",
90+
".#.######.########.#",
91+
".###.#######.####.#.",
92+
"#####.##.#.##.###.##",
93+
"..#####..#.#########",
94+
"####################",
95+
"#.####....###.#.#.##",
96+
"##.#################",
97+
"#####.##.###..####..",
98+
"..######..##.#######",
99+
"####.##.####...##..#",
100+
".#####..#.######.###",
101+
"##...#.##########...",
102+
"#.##########.#######",
103+
".####.#.###.###.#.##",
104+
"....##.##.###..#####",
105+
".#.#.###########.###",
106+
"#.#.#.#####.####.###",
107+
"###.##.####.##.#..##"
108+
], Vector(11,13), 210)
50109

51110
def part1():
52-
pass
111+
(asteroids, edge) = to_points(aoc.get_input().readlines())
112+
best = find_best(asteroids, edge)
113+
return best[1]
53114

54115
def part2():
55116
pass
56117

57-
def to_points(lines : List[str]) -> Tuple[Set[Vector], Set[Vector], Vector]:
118+
def to_points(lines : List[str]) -> Tuple[Set[Vector], Vector]:
58119
edge = Vector(len(lines[-1]) - 1, len(lines) - 1)
59120
asteroids = set()
60-
gaps = set()
61121
for x in range(edge.x+1):
62122
for y in range(edge.y+1):
63123
if lines[y][x] == "#": asteroids.add(Vector(x,y))
64-
elif lines[y][x] == ".": gaps.add(Vector(x,y))
65-
return (asteroids, gaps, edge)
124+
return (asteroids, edge)
66125

67126

68127
def edges(edge : Vector):
@@ -90,28 +149,50 @@ def rays(origin : Vector, edge : Vector, edge_vectors):
90149
rays.add(e)
91150
return rays
92151

152+
@lru_cache
153+
def rays_fixed(edge : Vector):
154+
def it(origin : Vector):
155+
for x in range(edge.x + 1):
156+
for y in range(edge.y + 1):
157+
ray = origin - Vector(x,y)
158+
if (g := math.gcd(origin.x - x, origin.y - y)) > 0:
159+
yield(ray // g)
160+
rays = set()
161+
rays.update(it(Vector( 0, 0 )))
162+
rays.update(it(Vector( edge.x, 0 )))
163+
rays.update(it(Vector( 0, edge.y )))
164+
rays.update(it(Vector( edge.x, edge.y )))
165+
return rays
166+
93167
def trace(origin : Vector, rays: Set[Vector], asteroids : Set[Vector], edge : Vector) -> Set[Vector]:
94168
for ray in rays:
95-
print(f" Tracing along {ray}", end="", flush=True)
169+
# print(f" Tracing along {ray}", end="", flush=True)
96170
p = origin + ray
97171
while in_field(p, edge):
98-
print(".", end="", flush=True)
172+
# print(".", end="", flush=True)
99173
if p in asteroids:
100174
yield p
101-
print(f"asteroid at {p}")
175+
# print(f"asteroid at {p}")
102176
break
103177
p = p + ray
104-
print()
105-
106-
def naive_raytrace(asteroids : Set[Vector], gaps : Set[Vector], edge : Vector):
107-
edge_vectors = set(edges(edge))
108-
109-
for gap in gaps:
110-
print(f"Tracing from {gap}")
111-
r = rays(gap, edge, edge_vectors)
112-
print(f" Got rays ({len(r)})")
113-
yield gap, trace(gap, r, asteroids, edge)
114-
178+
# print()
179+
180+
def naive_raytrace(asteroids : Set[Vector], edge : Vector):
181+
r = rays_fixed(edge)
182+
183+
for asteroid in asteroids:
184+
# print(f"Tracing from {asteroid}")
185+
# print(f" Got rays ({len(r)})")
186+
yield asteroid, trace(asteroid, r, asteroids, edge)
187+
188+
def find_best(asteroids : Set[Vector], edge : Vector):
189+
return max(
190+
map(
191+
lambda t: (t[0], len(set(t[1]))),
192+
naive_raytrace(asteroids, edge)
193+
),
194+
key=itemgetter(1)
195+
)
115196

116197
def print_field(mappings : Dict[str,Set[Vector]], edge : Vector):
117198
field = [[" "] * (edge.x + 1) for _ in range((edge.y + 1))]

0 commit comments

Comments
 (0)