Files
adventofcode/2015/day-22/solution.py
2016-12-01 11:25:19 +01:00

107 lines
2.7 KiB
Python

from __future__ import print_function, division
import heapq
def applyEffects(current):
if current['recharge'] > 0:
current['mana'] += 101
current['recharge'] -= 1
if current['shield'] > 0:
current['shield'] -= 1
if current['poison'] > 0:
current['poison'] -= 1
current['bossHP'] -= 3
def dijkstraMagic(initialState, hard):
todo = [(0, 0, initialState.copy())]
visited = {tuple(initialState.values()): 0}
iteration = 0
while todo:
iteration += 1
top = heapq.heappop(todo)
current = top[2].copy()
manaSpent = top[0]
if hard:
# Hard mode
current['hp'] -= 1
if current['hp'] <= 0:
# Already dead
continue
applyEffects(current)
if current['bossHP'] <= 0:
# We won!
return manaSpent
# Try every available spell
for spell in spells:
if current['mana'] < spell[1]:
# Not enough mana to cast
continue
if spell[4] is not None and current[spell[4]] > 0:
# Effect still active
continue
newState = current.copy()
newState['bossHP'] -= spell[2]
newState['mana'] -= spell[1]
newState['hp'] += spell[3]
if spell[4] is not None:
newState[spell[4]] = spell[5]
newMana = manaSpent + spell[1]
# Start Boss turn
applyEffects(newState)
if newState['bossHP'] > 0:
# Alive to attack?
if newState['shield'] > 0:
damage = 2
else:
damage = 9
newState['hp'] -= damage
else:
# Died during effects
return newMana
if newState['hp'] > 0:
# New state
key = tuple(newState.values())
if key not in visited or visited[key] > newMana:
# Insert the route in to the visited and queue
visited[key] = newMana
heapq.heappush(todo, (newMana, iteration, newState))
return None
spells = [
# Name, Mana, Damage, Heal, Effect, Turns
("Magic Missile", 53, 4, 0, None, 0),
("Drain", 73, 2, 2, None, 0),
("Shield", 113, 0, 0, "shield", 6),
("Poison", 173, 0, 0, "poison", 6),
("Recharge", 229, 0, 0, "recharge", 5),
]
status = {
"bossHP": 51,
"hp": 50,
"mana": 500,
"shield": 0,
"poison": 0,
"recharge": 0
}
print(dijkstraMagic(status, False))
print(dijkstraMagic(status, True))