From 4cb37bc59b695192ffc95fd686bea05e1bd931ab Mon Sep 17 00:00:00 2001 From: Tomasz Kramkowski Date: Sun, 10 Dec 2023 13:05:33 +0000 Subject: day 10 jank --- 10.py | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 10.py diff --git a/10.py b/10.py new file mode 100644 index 0000000..a024909 --- /dev/null +++ b/10.py @@ -0,0 +1,118 @@ +import re +from collections.abc import Iterator +from dataclasses import dataclass +from sys import stdin +from typing import Self + + +@dataclass(frozen=True, slots=True, order=True) +class Point: + x: int + y: int + + def __sub__(self, other: Self) -> Self: + return self.__class__(self.x - other.x, self.y - other.y) + + def __add__(self, other: Self) -> Self: + return self.__class__(self.x + other.x, self.y + other.y) + + def __neg__(self) -> Self: + return self.__class__(-self.x, -self.y) + + +def next_pos(current: Point, prev: Point, pipe: str) -> Point: + mapping = { + Point(0, 1): { # from north \/ + "|": Point(0, 1), # to south \/ + "L": Point(1, 0), # to east -> + "J": Point(-1, 0), # to west <- + }, + Point(-1, 0): { # from east <- + "-": Point(-1, 0), # to west <- + "F": Point(0, 1), # to south \/ + "L": Point(0, -1), # to north /\ + }, + Point(0, -1): { # from south /\ + "|": Point(0, -1), # to north /\ + "F": Point(1, 0), # to east -> + "7": Point(-1, 0), # to west <- + }, + Point(1, 0): { # from west -> + "-": Point(1, 0), # to east -> + "7": Point(0, 1), # to south \/ + "J": Point(0, -1), # to north /\ + }, + } + return current + mapping[current - prev][pipe] + + +def neighbours(point: Point) -> Iterator[Point]: + for d in (Point(0, -1), Point(1, 0), Point(0, 1), Point(-1, 0)): + yield point + d + + +inp = [line.rstrip() for line in stdin] + +start = next( + Point(x, y) for y, l in enumerate(inp) for x, c in enumerate(l) if c == "S" +) + +prev = start +if inp[start.y - 1][start.x] in {"|", "F", "7"}: + current = start + Point(0, -1) +elif inp[start.y][start.x + 1] in {"-", "J", "7"}: + current = start + Point(1, 0) +elif inp[start.y + 1][start.x] in {"|", "J", "L"}: + current = start + Point(0, 1) +elif inp[start.y][start.x - 1] in {"-", "L", "F"}: + current = start + Point(-1, 0) +else: + raise ValueError + +first_after_start = current +last_before_start = current + +bounds: set[Point] = set((start,)) +length = 1 +while inp[current.y][current.x] != "S": + bounds.add(current) + current, prev = next_pos(current, prev, inp[current.y][current.x]), current + last_before_start = prev + length += 1 + +print(length // 2) + +dirs = list(sorted((start - first_after_start, start - last_before_start))) + +start_replacement = { + "S": { + (Point(-1, 0), Point(0, -1)): "F", # ES + (Point(-1, 0), Point(0, 1)): "L", # EN + (Point(-1, 0), Point(1, 0)): "-", # EW + (Point(0, -1), Point(0, 1)): "|", # SN + (Point(0, -1), Point(1, 0)): "7", # SW + (Point(0, 1), Point(1, 0)): "J", # NW + }[(dirs[0], dirs[1])] +} + + +inp2 = [ + "".join( + start_replacement.get(c, c) if Point(x, y) in bounds else "." + for x, c in enumerate(line) + ) + for y, line in enumerate(inp) +] + +for pattern, repl in (("L-*J", ""), ("L-*7", "|"), ("F-*J", "|"), ("F-*7", "")): + inp2 = [re.sub(pattern, repl, l) for l in inp2] + +inner = 0 +for line in inp2: + outside = True + for c in line: + if c == "|": + outside = not outside + elif c == "." and not outside: + inner += 1 +print(inner) -- cgit v1.2.3-54-g00ecf