Created
December 24, 2015 19:01
-
-
Save salty-horse/ada2434398775c3c6adc to your computer and use it in GitHub Desktop.
Advent of Code - day 21 in Python 3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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