From fc2cad488b519fede26af783e78936643fbec82d Mon Sep 17 00:00:00 2001 From: Bruno BELANYI Date: Wed, 21 May 2025 22:19:08 +0100 Subject: [PATCH] 2015: d16: ex2: add solution --- 2015/d16/ex2/ex2.py | 69 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100755 2015/d16/ex2/ex2.py diff --git a/2015/d16/ex2/ex2.py b/2015/d16/ex2/ex2.py new file mode 100755 index 0000000..5711b59 --- /dev/null +++ b/2015/d16/ex2/ex2.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python + +import sys +from typing import NamedTuple + + +class Sue(NamedTuple): + children: int | None = None + cats: int | None = None + samoyeds: int | None = None + pomeranians: int | None = None + akitas: int | None = None + vizslas: int | None = None + goldfish: int | None = None + trees: int | None = None + cars: int | None = None + perfumes: int | None = None + + def matches(self, reading: dict[str, int | None]) -> bool: + for name, expected in reading.items(): + assert expected is not None # Sanity check + val = getattr(self, name) + if name in ("cats", "trees"): + if val is not None and val <= expected: + return False + elif name in ("pomeranians", "goldfish"): + if val is not None and val >= expected: + return False + else: + if val is not None and val != expected: + return False + return True + + +def solve(input: str) -> int: + def parse_line(input: str) -> Sue: + _, other = input.split(": ", 1) + raw_items = other.split(", ") + items = { + name: int(val) for name, val in (item.split(": ") for item in raw_items) + } + return Sue(**items) + + def parse(input: str) -> list[Sue]: + return [parse_line(line) for line in input.splitlines()] + + aunts = parse(input) + reading = Sue( + children=3, + cats=7, + samoyeds=2, + pomeranians=3, + akitas=0, + vizslas=0, + goldfish=5, + trees=3, + cars=2, + perfumes=1, + ) + return next(i for i, sue in enumerate(aunts, 1) if sue.matches(reading._asdict())) + + +def main() -> None: + input = sys.stdin.read() + print(solve(input)) + + +if __name__ == "__main__": + main()