diff --git a/2017/d22/ex1/ex1.py b/2017/d22/ex1/ex1.py new file mode 100755 index 0000000..3aab299 --- /dev/null +++ b/2017/d22/ex1/ex1.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python + +import dataclasses +import enum +import sys +from typing import NamedTuple + + +class Point(NamedTuple): + x: int + y: int + + +class Direction(enum.Enum): + UP = Point(-1, 0) + DOWN = Point(1, 0) + LEFT = Point(0, -1) + RIGHT = Point(0, 1) + + def left(self) -> "Direction": + x, y = self.value + return Direction(Point(-y, x)) + + def right(self) -> "Direction": + x, y = self.value + return Direction(Point(y, -x)) + + def apply(self, p: Point) -> Point: + dx, dy = self.value + return Point(p.x + dx, p.y + dy) + + +@dataclasses.dataclass +class Carrier: + pos: Point + dir: Direction + + def burst(self, infected: set[Point]) -> bool: + infect = False + if self.pos in infected: + self.dir = self.dir.right() + infected.remove(self.pos) + else: + self.dir = self.dir.left() + infected.add(self.pos) + infect = True + self.pos = self.dir.apply(self.pos) + return infect + + +def solve(input: str) -> int: + def parse(input: str) -> set[Point]: + return { + Point(x, y) + for x, line in enumerate(input.splitlines()) + for y, c in enumerate(line) + if c == "#" + } + + infected = parse(input) + middle = len(input.splitlines()) // 2 + carrier = Carrier(Point(middle, middle), Direction.UP) + total = 0 + + for _ in range(10000): + total += carrier.burst(infected) + return total + + +def main() -> None: + input = sys.stdin.read() + print(solve(input)) + + +if __name__ == "__main__": + main()