21.py
1 from lib import * 2 3 input = read_input(2015, 21) 4 5 (*_, boss_hp), (*_, boss_damage), (*_, boss_armor) = map(str.split, input.splitlines()) 6 7 boss_hp, boss_damage, boss_armor = map(int, [boss_hp, boss_damage, boss_armor]) 8 9 10 player_hp = 100 11 12 13 NEUTRAL = (0, 0, 0) 14 shop_weapons = [(8, 4, 0), (10, 5, 0), (25, 6, 0), (40, 7, 0), (74, 8, 0)] 15 shop_armor = [NEUTRAL, (13, 0, 1), (31, 0, 2), (53, 0, 3), (75, 0, 4), (102, 0, 5)] 16 shop_rings = [NEUTRAL, NEUTRAL, (25, 1, 0), (50, 2, 0), (100, 3, 0), (20, 0, 1), (40, 0, 2), (80, 0, 3)] 17 18 19 def fight(player_damage, player_armor): 20 player = player_hp 21 boss = boss_hp 22 while True: 23 boss -= max(1, player_damage - boss_armor) 24 if boss <= 0: 25 return True 26 player -= max(1, boss_damage - player_armor) 27 if player <= 0: 28 return False 29 30 31 def combine(*args): 32 return tuple(map(sum, zip(*args))) 33 34 35 best = 1e1337 36 for weapon in shop_weapons: 37 for armor in shop_armor: 38 for i, ring1 in enumerate(shop_rings): 39 for ring2 in shop_rings[i + 1 :]: 40 cost, d, a = combine(weapon, armor, ring1, ring2) 41 if fight(d, a): 42 best = min(best, cost) 43 print(best) 44 45 46 best = 0 47 for weapon in shop_weapons: 48 for armor in shop_armor: 49 for i, ring1 in enumerate(shop_rings): 50 for ring2 in shop_rings[i + 1 :]: 51 cost, d, a = combine(weapon, armor, ring1, ring2) 52 if not fight(d, a): 53 best = max(best, cost) 54 print(best)