Advent of code 2015 solutions https://adventofcode.com/2015/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

21.py 1.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. from collections import defaultdict
  2. from itertools import combinations, product
  3. from math import ceil
  4. weapons = {
  5. 'dagger': {'cost': 8, 'damage': 4},
  6. 'shortsword': {'cost': 10, 'damage': 5},
  7. 'warhammer': {'cost': 25, 'damage': 6},
  8. 'longsword': {'cost': 40, 'damage': 7},
  9. 'greataxe': {'cost': 74, 'damage': 8}
  10. }
  11. armour = {
  12. 'none': {'cost': 0},
  13. 'leather': {'cost': 13, 'armour': 1},
  14. 'chainmail': {'cost': 31, 'armour': 2},
  15. 'splintmail': {'cost': 53, 'armour': 3},
  16. 'bandedmail': {'cost': 75, 'armour': 4},
  17. 'platemail': {'cost': 102, 'armour': 5}
  18. }
  19. rings = {
  20. 'none1': {'cost': 0},
  21. 'none2': {'cost': 0},
  22. 'damage1': {'cost': 25, 'damage': 1},
  23. 'damage2': {'cost': 50, 'damage': 2},
  24. 'damage3': {'cost': 100, 'damage': 3},
  25. 'defense1': {'cost': 20, 'armour': 1},
  26. 'defense2': {'cost': 40, 'armour': 2},
  27. 'defense3': {'cost': 80, 'armour': 3}
  28. }
  29. boss_stats = {
  30. 'hp': 104,
  31. 'damage': 8,
  32. 'armour': 1
  33. }
  34. def get_loadouts():
  35. return product(weapons.values(), armour.values(), combinations(rings.values(), 2))
  36. def get_stats(loadout):
  37. weapon, armour, (ring1, ring2) = loadout
  38. stats = defaultdict(int)
  39. stats['hp'] = 100
  40. for part in (weapon, armour, ring1, ring2):
  41. for k, v in part.items():
  42. stats[k] += v
  43. stats['loadout'] = loadout
  44. return stats
  45. def will_win(my_stats, boss_stats):
  46. inflicted_dpt = max(1, my_stats['damage'] - boss_stats['armour'])
  47. received_dpt = max(1, boss_stats['damage'] - my_stats['armour'])
  48. boss_death_turn = ceil(boss_stats['hp'] / inflicted_dpt)
  49. my_death_turn = ceil(my_stats['hp'] / received_dpt)
  50. return my_death_turn >= boss_death_turn
  51. stats = (s for s in (get_stats(l) for l in get_loadouts()) if will_win(s, boss_stats))
  52. print(min(stats, key=lambda s: s['cost']))
  53. stats = (s for s in (get_stats(l) for l in get_loadouts()) if not will_win(s, boss_stats))
  54. print(max(stats, key=lambda s: s['cost']))