Files
aocpy/2019/d10.py
2024-08-10 14:22:19 -04:00

103 lines
2.5 KiB
Python

from lib import get_data, Grid2D
from math import gcd, atan2, pi
def angle(a1, a2):
dy = a1[0] - a2[0]
dx = a2[1] - a1[1]
a = (atan2(dx, dy) + 2 * pi) % (2 * pi)
return a
def dist(a1, a2):
return abs(a1[0] - a2[0]) + abs(a1[1] - a2[1])
def part_1(data):
g = Grid2D(data)
asts = g.find("#")
asts_set = set(asts)
best_ast = None
visible_max = 0
for a in asts:
visible = 0
for other in asts:
if a == other:
continue
x1, x2 = a[0], other[0]
y1, y2 = a[1], other[1]
if y1 == y2:
for x in range(min(x1, x2) + 1, max(x1, x2)):
if (x, y1) in asts_set:
break
else:
visible += 1
elif x1 == x2:
for y in range(min(y1, y2) + 1, max(y1, y2)):
if (x1, y) in asts_set:
break
else:
visible += 1
else:
dx = abs(x1 - x2)
dy = abs(y1 - y2)
g = gcd(dx, dy)
dx //= g
dy //= g
x, y = x1, y1
if x2 < x1:
dx = -dx
if y2 < y1:
dy = -dy
blocked = False
while True:
x += dx
y += dy
if (x, y) == (x2, y2):
break
if (x, y) in asts_set:
blocked = True
break
if not blocked:
visible += 1
if visible > visible_max:
visible_max = visible
best_ast = a
assert best_ast is not None
print(visible_max)
other_asts = [a for a in asts if a != best_ast]
removed_count = 0
while True:
removed = set()
other_asts = sorted(
other_asts, key=lambda a: (angle(best_ast, a), dist(best_ast, a))
)
lowest_angle = -1
for a in other_asts:
current_angle = angle(best_ast, a)
if current_angle > lowest_angle:
removed.add(a)
lowest_angle = current_angle
removed_count += 1
if removed_count == 200:
print(a[1] * 100 + a[0])
return
other_asts = [a for a in other_asts if a not in removed]
def main():
data = get_data(__file__)
part_1(data)
if __name__ == "__main__":
main()