aboutsummaryrefslogtreecommitdiff
path: root/2015/21/puzzles.py
blob: 103a2eb45a7a8996d061e7dc25aa26d4f28b0093 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#!/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:
		match i[0]:
			case "Weapon":
				w += 1
			case "Armor":
				a += 1
			case "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 = float('inf')
	# 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()