#!/usr/bin/env python # -*- encoding: utf-8; py-indent-offset: 4 -*- # Author: Sebastian Mark # CC-BY-SA (https://creativecommons.org/licenses/by-sa/4.0/deed.de) # pylint: disable=missing-module-docstring,missing-function-docstring,consider-using-f-string import re def readinput(): with open("input", "r", encoding="utf-8") as file: lines = [line.strip("\n") for line in file.readlines()] return lines def get_antinodes_for_pair(city: list, pos: tuple, twin: tuple, part: int) -> set: width = len(city[0]) height = len(city) antinodes_for_pair = set() # distance between pairs dy = pos[0] - twin[0] dx = pos[1] - twin[1] # add antinode(s) above upper antenna nxty = pos[0] + dy nxtx = pos[1] + dx while 0 <= nxty < height and 0 <= nxtx < width: antinodes_for_pair.add((nxty, nxtx)) if part == 1: break nxty += dy nxtx += dx # add antinode(s) below lower antenna nxty = twin[0] - dy nxtx = twin[1] - dx while 0 <= nxty < height and 0 <= nxtx < width: antinodes_for_pair.add((nxty, nxtx)) if part == 1: break nxty -= dy nxtx -= dx return antinodes_for_pair def get_antinodes_for_freq(city: list, freq: str, pos: tuple, part: int) -> set: starty = pos[0] antinodes_for_freq = set() # search downwards for twins twins = [] if starty <= len(city): for y in range(starty + 1, len(city)): x = city[y].find(freq) if x >= 0: twins.append((y, x)) for twin in twins: antinodes_for_freq |= get_antinodes_for_pair(city, pos, twin, part) return antinodes_for_freq def get_antinodes(city: list, part: int) -> set: antinodes = set() # serch city for antennas for y, street in enumerate(city): antennas = re.finditer(r"([a-zA-Z0-9])", street) for antenna in antennas: freq = antenna.group() pos = (y, antenna.start()) antinodes |= get_antinodes_for_freq(city, freq, pos, part) if part == 2: antinodes.add(pos) return antinodes def main(): city = readinput() for part in [1, 2]: antinodes = get_antinodes(city, part) print("Unique antinodes (part%d): %d" % (part, len(antinodes))) if __name__ == "__main__": main()