From a7a6b86002b595bc167af72606b14c67ed1bdf8f Mon Sep 17 00:00:00 2001 From: Tomasz Kramkowski Date: Wed, 24 Nov 2021 22:25:42 +0000 Subject: init commit --- 15/input | 4 +++ 15/solution.py | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 15/input create mode 100644 15/solution.py (limited to '15') diff --git a/15/input b/15/input new file mode 100644 index 0000000..634c6a5 --- /dev/null +++ b/15/input @@ -0,0 +1,4 @@ +Frosting: capacity 4, durability -2, flavor 0, texture 0, calories 5 +Candy: capacity 0, durability 5, flavor -1, texture 0, calories 8 +Butterscotch: capacity -1, durability 0, flavor 5, texture 0, calories 6 +Sugar: capacity 0, durability 0, flavor -2, texture 2, calories 1 diff --git a/15/solution.py b/15/solution.py new file mode 100644 index 0000000..21b4ec8 --- /dev/null +++ b/15/solution.py @@ -0,0 +1,86 @@ +from dataclasses import dataclass +from functools import cache, cached_property +from itertools import combinations_with_replacement + +@dataclass +class Ingredient: + capacity: int + durability: int + flavor: int + texture: int + calories: int + + @cached_property + def score(self): + return max(self.capacity, 0) * max(self.durability, 0) * max(self.flavor, 0) * max(self.texture, 0) + + @cached_property + def calories_score(self): + return self.score if self.calories == 500 else 0 + + def __lt__(self, other): + return self.score < other.score + def __gt__(self, other): + return self.score > other.score + def __le__(self, other): + return self.score <= other.score + def __ge__(self, other): + return self.score >= other.score + def __add__(self, other): + return Ingredient( + self.capacity + other.capacity, + self.durability + other.durability, + self.flavor + other.flavor, + self.texture + other.texture, + self.calories + other.calories + ) + def __mul__(self, other: int) -> 'Ingredient': + return Ingredient( + self.capacity * other, + self.durability * other, + self.flavor * other, + self.texture * other, + self.calories * other + ) + + @staticmethod + def from_string(string) -> 'Ingredient': + _, rest = string.split(': ') + capacity, durability, flavor, texture, calories = (int(p.split()[1]) for p in rest.split(', ')) + return Ingredient(capacity, durability, flavor, texture, calories) + + +# def part1(ingredients: list[Ingredient]) -> int: +# @cache +# def max_score(capacity: int) -> Properties: +# if capacity == 0: +# return Properties(0, 0, 0, 0, 0) +# return max(max_score(capacity - 1) + ingredient.properties for ingredient in ingredients) +# s = max_score(100).score +# print(max_score.cache_info()) +# return s + +# def part1(ingredients: list[Ingredient]) -> int: +# return max(sum(perm) for perm in combinations_with_replacement([i.properties for i in ingredients], 100)).score + +def splits(total: int, segments: int) -> int: + if segments <= 1: + yield [total] + else: + for i in range(total + 1): + for subsplit in splits(total - i, segments - 1): + yield [i] + subsplit + +def part1(ingredients: list[Ingredient]) -> int: + empty = Ingredient(0, 0, 0, 0, 0) + return max(sum((ingredients[i] * q for i, q in enumerate(split)), start=empty).score for split in splits(100, len(ingredients))) + +def part2(ingredients: list[Ingredient]) -> int: + empty = Ingredient(0, 0, 0, 0, 0) + return max(sum((ingredients[i] * q for i, q in enumerate(split)), start=empty).calories_score for split in splits(100, len(ingredients))) + +if __name__ == '__main__': + with open('input') as f: + ingredients = [Ingredient.from_string(line.strip()) for line in f] + print(part1(ingredients)) + print(part2(ingredients)) -- cgit v1.2.3-54-g00ecf