from itertools import combinations def in_bounds(pos, grid): x, y = int(pos.real), int(pos.imag) if 0 <= y < len(grid) and 0 <= x < len(grid[0]): return True return False def part1(locations, grid): antinodes = set() for first, second in combinations(locations.items(), 2): first_loc, first_freq = first second_loc, second_freq = second if first_freq == second_freq: slope = first_loc - second_loc a = first_loc + slope if in_bounds(a, grid): antinodes.add(a) b = second_loc - slope if in_bounds(b, grid): antinodes.add(b) return antinodes def part2(locations, grid): antinodes = set() for first, second in combinations(locations.items(), 2): first_loc, first_freq = first second_loc, second_freq = second antinodes.update([first_loc, second_loc]) if first_freq == second_freq: slope = first_loc - second_loc i = 1 while True: a = first_loc + i*slope if not in_bounds(a, grid): break antinodes.add(a) i += 1 j = 0 while True: b = second_loc - j*slope if not in_bounds(b, grid): break antinodes.add(b) j += 1 return antinodes def main(lines): grid = [l.rstrip() for l in lines] locations = {} for y, row in enumerate(grid): for x, c in enumerate(row): if c != '.': locations[complex(x, y)] = c print("Part 1: ", len(part1(locations, grid))) print("Part 2: ", len(part2(locations, grid))) if __name__ == "__main__": import sys infile = sys.argv[1] if len(sys.argv) > 1 else "example.txt" with open(infile) as f: main(f.readlines())