Day 22: Wizard Simulator 20XX
Section
defmodule Game do
def apply_effects(ph, pa, pm, ps, pp, pr, bh, bd, turn) do
pa = if ps > 0, do: pa + 7, else: pa
ps = if ps > 0, do: ps - 1, else: ps
bh = if pp > 0, do: bh - 3, else: bh
pp = if pp > 0, do: pp - 1, else: pp
pm = if pr > 0, do: pm + 101, else: pm
pr = if pr > 0, do: pr - 1, else: pr
{ph, pa, pm, ps, pp, pr, bh, bd, turn}
end
def play(ph, pa, pm, ps, pp, pr, bh, bd, turn) do
q = [{ph, pa, pm, ps, pp, pr, bh, bd, turn, 0}]
min_spent = :infinity
process_queue(q, min_spent)
end
defp process_queue([], min_spent), do: min_spent
defp process_queue([{ph, _pa, pm, ps, pp, pr, bh, bd, turn, spent} | rest], min_spent) do
if spent > min_spent do
process_queue(rest, min_spent)
else
pa = 0
{ph, pa, pm, ps, pp, pr, bh, bd, turn} = apply_effects(ph, pa, pm, ps, pp, pr, bh, bd, turn)
if ph <= 0 do
process_queue(rest, min_spent)
else
if bh <= 0 do
process_queue(rest, min(min_spent, spent))
else
new_turn = rem(turn + 1, 2)
new_states =
if turn == 0 do
[]
|> add_if(pm >= 53, {ph, pa, pm - 53, ps, pp, pr, bh - 4, bd, new_turn, spent + 53})
|> add_if(
pm >= 73,
{ph + 2, pa, pm - 73, ps, pp, pr, bh - 2, bd, new_turn, spent + 73}
)
|> add_if(
ps == 0 and pm >= 113,
{ph, pa, pm - 113, ps + 6, pp, pr, bh, bd, new_turn, spent + 113}
)
|> add_if(
pp == 0 and pm >= 173,
{ph, pa, pm - 173, ps, pp + 6, pr, bh, bd, new_turn, spent + 173}
)
|> add_if(
pr == 0 and pm >= 229,
{ph, pa, pm - 229, ps, pp, pr + 5, bh, bd, new_turn, spent + 229}
)
else
damage = max(1, bd - pa)
if ph - damage > 0 do
[{ph - damage, pa, pm, ps, pp, pr, bh, bd, new_turn, spent}]
else
[]
end
end
process_queue(Enum.concat(rest, new_states), min_spent)
end
end
end
end
defp add_if(list, condition, value) do
if condition, do: [value | list], else: list
end
end
Game.play(50, 0, 500, 0, 0, 0, 55, 8, 0)
953
defmodule Game2 do
def apply_effects(ph, pa, pm, ps, pp, pr, bh, bd, turn) do
pa = if ps > 0, do: pa + 7, else: pa
ps = if ps > 0, do: ps - 1, else: ps
bh = if pp > 0, do: bh - 3, else: bh
pp = if pp > 0, do: pp - 1, else: pp
pm = if pr > 0, do: pm + 101, else: pm
pr = if pr > 0, do: pr - 1, else: pr
{ph, pa, pm, ps, pp, pr, bh, bd, turn}
end
def play2(ph, pa, pm, ps, pp, pr, bh, bd, turn) do
q = [{ph, pa, pm, ps, pp, pr, bh, bd, turn, 0}]
min_spent = :infinity
process_queue(q, min_spent)
end
defp process_queue([], min_spent), do: min_spent
defp process_queue([{ph, _pa, pm, ps, pp, pr, bh, bd, turn, spent} | rest], min_spent) do
if spent > min_spent do
process_queue(rest, min_spent)
else
ph = if turn == 0, do: ph - 1, else: ph
pa = 0
{ph, pa, pm, ps, pp, pr, bh, bd, turn} = apply_effects(ph, pa, pm, ps, pp, pr, bh, bd, turn)
if ph <= 0 do
process_queue(rest, min_spent)
else
if bh <= 0 do
process_queue(rest, min(min_spent, spent))
else
new_turn = rem(turn + 1, 2)
new_states =
if turn == 0 do
[]
|> add_if(pm >= 53, {ph, pa, pm - 53, ps, pp, pr, bh - 4, bd, new_turn, spent + 53})
|> add_if(
pm >= 73,
{ph + 2, pa, pm - 73, ps, pp, pr, bh - 2, bd, new_turn, spent + 73}
)
|> add_if(
ps == 0 and pm >= 113,
{ph, pa, pm - 113, ps + 6, pp, pr, bh, bd, new_turn, spent + 113}
)
|> add_if(
pp == 0 and pm >= 173,
{ph, pa, pm - 173, ps, pp + 6, pr, bh, bd, new_turn, spent + 173}
)
|> add_if(
pr == 0 and pm >= 229,
{ph, pa, pm - 229, ps, pp, pr + 5, bh, bd, new_turn, spent + 229}
)
else
damage = max(1, bd - pa)
if ph - damage > 0 do
[{ph - damage, pa, pm, ps, pp, pr, bh, bd, new_turn, spent}]
else
[]
end
end
process_queue(Enum.concat(rest, new_states), min_spent)
end
end
end
end
defp add_if(list, condition, value) do
if condition, do: [value | list], else: list
end
end
Game2.play2(50, 0, 500, 0, 0, 0, 55, 8, 0)
1289