116 lines
3.4 KiB
Python
116 lines
3.4 KiB
Python
#!/usr/bin/python
|
|
|
|
import re
|
|
from math import ceil
|
|
|
|
RE_STORE_HEADER = re.compile(r'^(.*):.*$')
|
|
RE_STORE_ITEM = re.compile(r'^(.*)\s+(\d+)\s+(\d+)\s+(\d+)')
|
|
RE_INPUT = re.compile(r'^(.*):\s+(\d+)$')
|
|
|
|
|
|
def read_file(filename):
|
|
file = open(filename, 'r')
|
|
while True:
|
|
line = file.readline()
|
|
if not line:
|
|
break
|
|
yield line
|
|
|
|
|
|
def simulate(me, boss):
|
|
myWinTurns = 0
|
|
bossWinTurns = 0
|
|
|
|
myWinTurns = int(ceil(boss['Hit Points'] / max(1, me['Damage'] - boss['Armor'])))
|
|
bossWinTurns = int(ceil(me['Hit Points'] / max(1, boss['Damage'] - me['Armor'])))
|
|
return(myWinTurns, bossWinTurns)
|
|
|
|
|
|
def calculate_possible_combinations(minSum, maxSum, pos, usage):
|
|
if pos == len(usage):
|
|
if sum(usage) >= minSum and sum(usage) <= maxSum:
|
|
yield usage
|
|
return
|
|
|
|
for x in range(2):
|
|
usage[pos] = x
|
|
for c in calculate_possible_combinations(minSum, maxSum, pos+1, usage):
|
|
yield c
|
|
usage[pos] = 0
|
|
|
|
|
|
def calculate_sum_product(item, usage, key):
|
|
sum = 0
|
|
for x in range(len(item)):
|
|
sum += item[x][key]*usage[x]
|
|
return sum
|
|
|
|
|
|
def buy(store):
|
|
# 1 Weapon
|
|
# 0-1 Armor
|
|
# 0-2 Rings
|
|
|
|
numWeapons = len(store['Weapons'])
|
|
numArmor = len(store['Armor'])
|
|
numRings = len(store['Rings'])
|
|
|
|
weapons = [0 for x in range(numWeapons)]
|
|
armor = [0 for x in range(numArmor)]
|
|
rings = [0 for x in range(numRings)]
|
|
|
|
for w in calculate_possible_combinations(1, numWeapons, 0, weapons):
|
|
for a in calculate_possible_combinations(0, numArmor, 0, armor):
|
|
for r in calculate_possible_combinations(0, numRings, 0, rings):
|
|
costS = calculate_sum_product(store['Weapons'], w, 'Cost')
|
|
costS += calculate_sum_product(store['Armor'], a, 'Cost')
|
|
costS += calculate_sum_product(store['Rings'], r, 'Cost')
|
|
armorS = calculate_sum_product(store['Weapons'], w, 'Armor')
|
|
armorS += calculate_sum_product(store['Armor'], a, 'Armor')
|
|
armorS += calculate_sum_product(store['Rings'], r, 'Armor')
|
|
damageS = calculate_sum_product(store['Weapons'], w, 'Damage')
|
|
damageS += calculate_sum_product(store['Armor'], a, 'Damage')
|
|
damageS += calculate_sum_product(store['Rings'], r, 'Damage')
|
|
yield (costS, damageS, armorS)
|
|
|
|
|
|
def main():
|
|
|
|
boss = dict()
|
|
store = dict()
|
|
me = dict()
|
|
|
|
for line in read_file('input'):
|
|
match = re.match(RE_INPUT, line)
|
|
boss[match.group(1)] = int(match.group(2))
|
|
|
|
store_group = None
|
|
for line in read_file('store'):
|
|
match = re.match(RE_STORE_HEADER, line)
|
|
if match:
|
|
store_group = match.group(1)
|
|
store[store_group] = []
|
|
continue
|
|
match = re.match(RE_STORE_ITEM, line)
|
|
if match:
|
|
item = dict()
|
|
item['Name'] = match.group(1).strip()
|
|
item['Cost'] = int(match.group(2))
|
|
item['Damage'] = int(match.group(3))
|
|
item['Armor'] = int(match.group(4))
|
|
store[store_group].append(item)
|
|
|
|
me['Hit Points'] = 100
|
|
me['Damage'] = 0
|
|
me['Armor'] = 0
|
|
|
|
for (c, d, a) in buy(store):
|
|
me['Damage'] = d
|
|
me['Armor'] = a
|
|
(turnMe, trunBoss) = simulate(me, boss)
|
|
if turnMe >= trunBoss:
|
|
print c
|
|
|
|
if __name__ == "__main__":
|
|
main()
|