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()