diff options
Diffstat (limited to '16/solution.py')
-rw-r--r-- | 16/solution.py | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/16/solution.py b/16/solution.py new file mode 100644 index 0000000..b7ebc5c --- /dev/null +++ b/16/solution.py @@ -0,0 +1,77 @@ +from dataclasses import dataclass + +@dataclass +class SueQuality: + quality: int | None = None + + def __eq__(self, other): + return self.quality is None or other.quality is None or self.quality == other.quality + + def __gt__(self, other): + return self.quality is None or other.quality is None or self.quality > other.quality + def __lt__(self, other): + return self.quality is None or other.quality is None or self.quality < other.quality + +@dataclass +class Sue: + children: SueQuality = SueQuality() + cats: SueQuality = SueQuality() + samoyeds: SueQuality = SueQuality() + pomeranians: SueQuality = SueQuality() + akitas: SueQuality = SueQuality() + vizslas: SueQuality = SueQuality() + goldfish: SueQuality = SueQuality() + trees: SueQuality = SueQuality() + cars: SueQuality = SueQuality() + perfumes: SueQuality = SueQuality() + + def cmp(self, other: 'Sue') -> bool: + for attr in self.__dict__: + if getattr(self, attr) != getattr(other, attr): + return False + return True + + def cmp2(self, other: 'Sue') -> bool: + return ( + self.children == other.children and + self.cats > other.cats and + self.samoyeds == other.samoyeds and + self.pomeranians < other.pomeranians and + self.akitas == other.akitas and + self.vizslas == other.vizslas and + self.goldfish < other.goldfish and + self.trees > other.trees and + self.cars == other.cars and + self.perfumes == other.perfumes + ) + + @staticmethod + def from_string(s: str) -> tuple[int, 'Sue']: + number, rest = s.split(': ', 1) + number = int(number.split(' ')[1]) + properties = {p[0]: SueQuality(int(p[1])) for p in (prop.split(': ') for prop in rest.split(', '))} + return number, Sue(**properties) + +def part1(sues: list[Sue]) -> int: + desired = Sue( + children=SueQuality(3), cats=SueQuality(7), samoyeds=SueQuality(2), + pomeranians=SueQuality(3), akitas=SueQuality(0), vizslas=SueQuality(0), + goldfish=SueQuality(5), trees=SueQuality(3), cars=SueQuality(2), + perfumes=SueQuality(1) + ) + return next(number for number, sue in sues.items() if sue.cmp(desired)) + +def part2(sues: list[Sue]) -> int: + desired = Sue( + children=SueQuality(3), cats=SueQuality(7), samoyeds=SueQuality(2), + pomeranians=SueQuality(3), akitas=SueQuality(0), vizslas=SueQuality(0), + goldfish=SueQuality(5), trees=SueQuality(3), cars=SueQuality(2), + perfumes=SueQuality(1) + ) + return next(number for number, sue in sues.items() if sue.cmp2(desired)) + +if __name__ == '__main__': + with open('input') as f: + sues = {number: sue for number, sue in (Sue.from_string(line) for line in f)} + print(part1(sues)) + print(part2(sues)) |