From 8f0bc54b7c90c7cb495a93cb687ff57afddf4528 Mon Sep 17 00:00:00 2001 From: Sebastian Mark Date: Sun, 8 Dec 2024 20:20:40 +0100 Subject: [PATCH] add 2024/day8 --- 2024/08/main.py | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 2024/08/main.py diff --git a/2024/08/main.py b/2024/08/main.py new file mode 100644 index 0000000..0f23a1d --- /dev/null +++ b/2024/08/main.py @@ -0,0 +1,94 @@ +#!/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()