From a035967ba6e2f1c07f2004878ecc2846e6eb72d4 Mon Sep 17 00:00:00 2001 From: Bruno BELANYI Date: Sun, 29 Dec 2024 15:26:09 -0500 Subject: [PATCH] 2018: d03: ex1: add solution --- 2018/d03/ex1/ex1.py | 51 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100755 2018/d03/ex1/ex1.py diff --git a/2018/d03/ex1/ex1.py b/2018/d03/ex1/ex1.py new file mode 100755 index 0000000..b5feb37 --- /dev/null +++ b/2018/d03/ex1/ex1.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python + +import itertools +import sys +from collections import Counter +from collections.abc import Iterator +from typing import NamedTuple + + +class Point(NamedTuple): + x: int + y: int + + +class Claim(NamedTuple): + top_left: Point + size: Point + + def points(self) -> Iterator[Point]: + for dx, dy in map( + Point._make, itertools.product(range(self.size.x), range(self.size.y)) + ): + yield Point(self.top_left.x + dx, self.top_left.y + dy) + + +def solve(input: str) -> int: + def parse_claim(input: str) -> Claim: + offset, size = input.split("@")[1].strip().split(": ") + return Claim( + Point(*map(int, offset.split(","))), + Point(*map(int, size.split("x"))), + ) + + def parse(input: list[str]) -> list[Claim]: + return [parse_claim(line) for line in input] + + def claim_per_point(claims: list[Claim]) -> dict[Point, int]: + points = itertools.chain.from_iterable(map(Claim.points, claims)) + return Counter(points) + + claims = parse(input.splitlines()) + return sum(count > 1 for count in claim_per_point(claims).values()) + + +def main() -> None: + input = sys.stdin.read() + print(solve(input)) + + +if __name__ == "__main__": + main()