diff options
Diffstat (limited to '2015')
-rw-r--r-- | 2015/21/.gitignore | 1 | ||||
-rw-r--r-- | 2015/21/Makefile | 8 | ||||
-rw-r--r-- | 2015/21/input | 3 | ||||
-rw-r--r-- | 2015/21/puzzles.py | 89 |
4 files changed, 101 insertions, 0 deletions
diff --git a/2015/21/.gitignore b/2015/21/.gitignore new file mode 100644 index 0000000..ffc46fe --- /dev/null +++ b/2015/21/.gitignore @@ -0,0 +1 @@ +puzzle-[12].py diff --git a/2015/21/Makefile b/2015/21/Makefile new file mode 100644 index 0000000..9f0c9fb --- /dev/null +++ b/2015/21/Makefile @@ -0,0 +1,8 @@ +all: + sed '/# START PART 2/,/# END PART 2/d' puzzles.py >puzzle-1.py + sed '/# START PART 1/,/# END PART 1/d' puzzles.py >puzzle-2.py + chmod +x puzzle-[12].py + +.PHONY: clean +clean: + rm -f puzzle-[12].py diff --git a/2015/21/input b/2015/21/input new file mode 100644 index 0000000..e749051 --- /dev/null +++ b/2015/21/input @@ -0,0 +1,3 @@ +Hit Points: 103 +Damage: 9 +Armor: 2 diff --git a/2015/21/puzzles.py b/2015/21/puzzles.py new file mode 100644 index 0000000..48e8c4e --- /dev/null +++ b/2015/21/puzzles.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python3 + + +import itertools +import math + +SHOP = [ + ("Weapon", 8, 4, 0), + ("Weapon", 10, 5, 0), + ("Weapon", 25, 6, 0), + ("Weapon", 40, 7, 0), + ("Weapon", 74, 8, 0), + ("Armor", 0, 0, 0), + ("Armor", 13, 0, 1), + ("Armor", 31, 0, 2), + ("Armor", 53, 0, 3), + ("Armor", 75, 0, 4), + ("Armor", 102, 0, 5), + ("Ring", 0, 0, 0), + ("Ring", 0, 0, 0), + ("Ring", 25, 1, 0), + ("Ring", 50, 2, 0), + ("Ring", 100, 3, 0), + ("Ring", 20, 0, 1), + ("Ring", 40, 0, 2), + ("Ring", 80, 0, 3), +] + + +def wins(d: int, hp: int) -> bool: + turns = hp / d + if turns > int(turns): + turns = math.ceil(turns) + + return (turns - 1) * d < 100 + + +def valid(e: tuple[tuple[str, int, int, int], ...]) -> bool: + w = a = r = 0 + for i in e: + if i[0] == "Weapon": + w += 1 + elif i[0] == "Armor": + a += 1 + elif i[0] == "Ring": + r += 1 + return (w == 1) and (a <= 1) and (r <= 2) + + +def main() -> None: + with open("input", "r", encoding="utf-8") as f: + b_health, b_damage, b_armor = f.readlines() + b_health = int(b_health.strip().split(": ")[1]) + b_damage = int(b_damage.strip().split(": ")[1]) + b_armor = int(b_armor.strip().split(": ")[1]) + + # START PART 1 + min_cost = 999999999999999999999999999999999999999999999999999999999 + # END PART 1 + # START PART 2 + max_cost = 0 + # END PART 2 + + for combs in [itertools.combinations(SHOP, i) for i in range(1, 5)]: + for comb in list(filter(valid, combs)): + cost = sum(x[1] for x in comb) + damage = sum(x[2] for x in comb) + armor = sum(x[3] for x in comb) + delta = (damage - b_armor) - (b_damage - armor) + + # START PART 1 + if (delta > 0) or ((delta == 0) and wins(damage - b_armor, b_health)): + min_cost = min(cost, min_cost) + # END PART 1 + # START PART 2 + if (delta < 0) or ((delta == 0) and not wins(damage - b_armor, b_health)): + max_cost = max(cost, max_cost) + # END PART 2 + + # START PART 1 + print(min_cost) + # END PART 1 + # START PART 2 + print(max_cost) + # END PART 2 + + +if __name__ == "__main__": + main() |