You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
2.8 KiB

from collections import defaultdict
import time
import numpy as np
DIM = 40
EX = [
".#....#####...#..",
"##...##.#####..##",
"##...#...#.#####.",
"..#.....#...###..",
"..#.#.....#....##",
]
def main():
with open("day10.txt", "rt") as input_file:
amap = [line.rstrip() for line in input_file.readlines()]
# amap = [line.rstrip() for line in EX]
asteroids = []
for y, line in enumerate(amap):
for x, value in enumerate(line):
if value == "#":
asteroids.append((x, y))
# Part 1
best_vis = 0
best_pos = None
for pos in asteroids:
vis = num_visible_asts(asteroids, pos)
if vis > best_vis:
best_vis, best_pos = vis, pos
print(f"Best visibility is {best_vis} at {best_pos}.")
# Part 2
pos = best_pos
asteroids.remove(pos)
destroyed = 0
angles = defaultdict(list)
for a in asteroids:
angle = np.angle(np.complex(a[0] - pos[0], a[1] - pos[1]), deg=True)
angles[angle].append(a)
current_angle = -90.0
while asteroids:
print(f"Laser at {pos}.")
print(f"Current angle: {current_angle}.")
targets = angles[current_angle]
try:
next_angle = min([a for a in angles.keys() if a > current_angle])
except ValueError:
next_angle = -180.0
if not targets:
current_angle = next_angle
continue
print(f"Acquired targets {targets}.")
nearest_target = min(targets, key=lambda t: dist_idea(pos, t))
print(f"Nearest target: {nearest_target}.")
# Pew!
asteroids.remove(nearest_target)
targets.remove(nearest_target)
destroyed += 1
print(f"Destroyed {nearest_target} -- total of {destroyed} asteroids.")
if destroyed == 200:
print(f"Destroyed 200th asteroid at {nearest_target}.")
break
current_angle = next_angle
draw(asteroids, pos, [nearest_target])
time.sleep(0.2)
print(f"Answer: {100 * nearest_target[0] + nearest_target[1]}.")
def draw(asteroids, station_pos, specials=[]):
for y in range(DIM):
print(str(y).zfill(2), end=" ")
for x in range(DIM):
if (x, y) == station_pos:
print("@", end="")
elif (x, y) in specials:
print("X", end="")
elif (x, y) in asteroids:
print("", end="")
else:
print(" ", end="")
print()
print(" " + "0123456789"*4)
def num_visible_asts(asteroids, ref):
asteroids = asteroids.copy()
asteroids.remove(ref)
angles = [np.angle(np.complex(a[0] - ref[0], a[1] - ref[1])) for a in asteroids]
return len(set(angles))
def dist_idea(a, b):
return (a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2
if __name__ == "__main__":
main()