116 lines
3.4 KiB
Python
Raw Permalink Normal View History

2016-08-08 07:32:56 +02:00
#!/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()