Skip to content

Instantly share code, notes, and snippets.

@salty-horse
Created December 24, 2015 19:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save salty-horse/ada2434398775c3c6adc to your computer and use it in GitHub Desktop.
Save salty-horse/ada2434398775c3c6adc to your computer and use it in GitHub Desktop.
Advent of Code - day 21 in Python 3
#!/usr/bin/env python3
import math
import itertools
class Stats(object):
def __init__(self, hp, damage, armor):
self.hit_points = hp
self.damage = damage
self.armor = armor
class Item(object):
def __init__(self, cost, damage, armor):
self.cost = cost
self.damage = damage
self.armor = armor
def __repr__(self):
return 'Item({}, {}, {})'.format(self.cost, self.damage, self.armor)
WEAPONS = [
Item( 8, 4, 0),
Item(10, 5, 0),
Item(25, 6, 0),
Item(40, 7, 0),
Item(74, 8, 0),
]
ARMOR = [
Item( 13, 0, 1),
Item( 31, 0, 2),
Item( 53, 0, 3),
Item( 75, 0, 4),
Item(102, 0, 5),
];
RINGS = [
Item( 25, 1, 0),
Item( 50, 2, 0),
Item(100, 3, 0),
Item( 20, 0, 1),
Item( 40, 0, 2),
Item( 80, 0, 3),
];
def choose_items(items, at_least, at_most=None):
if at_most is None:
at_most = len(items)
for i in range(at_least, at_most+1):
yield from itertools.combinations(items, i)
def does_player_win(player, boss):
player_damage = max(player.damage - boss.armor, 1)
player_wins_at = math.ceil(boss.hit_points / player_damage)
boss_damage = max(boss.damage - player.armor, 1)
boss_wins_at = math.ceil(player.hit_points / boss_damage)
return player_wins_at <= boss_wins_at
def main():
input_fname = 'day21_input.txt'
with open(input_fname) as f:
boss_hitpoints = int(f.readline().split(': ')[1])
boss_damage = int(f.readline().split(': ')[1])
boss_armor = int(f.readline().split(': ')[1])
boss = Stats(boss_hitpoints, boss_damage, boss_armor)
player_hitpoints = 100
min_cost = None
for weapons in choose_items(WEAPONS, 1, 1):
for armors in choose_items(ARMOR, 0, 1):
for rings in choose_items(RINGS, 0, 2):
damage = 0
armor = 0
cost = 0
for item in itertools.chain(weapons, armors, rings):
damage += item.damage
armor += item.armor
cost += item.cost
if does_player_win(
Stats(player_hitpoints, damage, armor),
boss):
if min_cost is None or cost < min_cost:
min_cost = cost
print('Min cost:', min_cost)
max_cost = None
for weapons in choose_items(WEAPONS, 1):
for armors in choose_items(ARMOR, 0):
for rings in choose_items(RINGS, 0):
damage = 0
armor = 0
cost = 0
for item in itertools.chain(weapons, armors, rings):
damage += item.damage
armor += item.armor
cost += item.cost
if not does_player_win(
Stats(player_hitpoints, damage, armor),
boss):
if max_cost is None or cost > max_cost:
max_cost = cost
print('Max cost to lose:', max_cost)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment