2024-12-08 - Resonant Collinearity
(original .ipynb)
Day 8 puzzle input is a grid showing the positions of certain antennae each operating on different frequencies (same letter/digit = same frequency), mine is here). Part 1 involves finding "antinodes" (can't be bothered explaining, it's stupid) and counting how many there are. Part 2 involves adjusting how the "antinodes" are calculated and counting them again.
from collections import defaultdict
from itertools import combinations
puzzle_input_str = open("./puzzle_input/day8.txt").read()
test_input_str = """............
........0...
.....0......
.......0....
....0.......
......A.....
............
............
........A...
.........A..
............
............"""
def parse_input(input_str):
input_lines = input_str.splitlines()
antennas = defaultdict(lambda:[])
for r, row in enumerate(input_lines):
for c, col in enumerate(row):
if col != ".":
antennas[col].append((r, c))
return antennas, len(input_lines), len(input_lines[0])
def antinodes(pos_a_r, pos_a_c, pos_b_r, pos_b_c):
dr = pos_a_r-pos_b_r
dc = pos_a_c-pos_b_c
return (
(pos_a_r+dr, pos_a_c+dc),
(pos_b_r-dr, pos_b_c-dc),
)
def in_graph(max_r, max_c, r, c):
return r >= 0 and r < max_r and c >= 0 and c < max_c
def part_one(input_str):
all_antennas, max_r, max_c = parse_input(input_str)
antinode_positions = set()
for antenna_name, antennas in all_antennas.items():
for antenna_a, antenna_b in combinations(antennas, 2):
for antinode in antinodes(*antenna_a, *antenna_b):
if in_graph(max_r, max_c, *antinode):
antinode_positions.add(antinode)
return len(antinode_positions)
assert 14 == part_one(test_input_str)
print("part one:", part_one(puzzle_input_str))
part one: 291
from itertools import chain
def antinodes_2(max_r, max_c, pos_a_r, pos_a_c, pos_b_r, pos_b_c):
dr_base = pos_a_r-pos_b_r
dc_base = pos_a_c-pos_b_c
for dr, dc in ((dr_base, dc_base), (-dr_base, -dc_base)):
for start_r, start_c in ((pos_a_r, pos_a_c), (pos_b_r, pos_b_c)):
r, c = start_r+dr, start_c+dc
while in_graph(max_r, max_c, r, c):
yield (r, c)
r += dr
c += dc
def part_two(input_str):
all_antennas, max_r, max_c = parse_input(input_str)
antinode_positions = set()
for antenna_name, antennas in all_antennas.items():
for antenna_a, antenna_b in combinations(antennas, 2):
for antinode in antinodes_2(max_r, max_c, *antenna_a, *antenna_b):
if in_graph(max_r, max_c, *antinode):
antinode_positions.add(antinode)
return len(antinode_positions)
assert 34 == part_two(test_input_str)
print("part two:", part_two(puzzle_input_str))
part two: 1015