* Solve 2015:16 "Aunt Sue" * Make 2023:08 future compatible Code used to work with another version of python. * Solve 2015:17 "No such Thing as Too much" * Solve 2015:18 "Like a GIF For Your Yard" Also solve 2015:06 just in case, was just a ref in the end. * Solve 2015:19 "Medicine for Rudolph" * Solve 2015:20 "Infinite Elves and Infinite Houses" * Solve 2023:21 "RPG Simulator 20XX" * Solve 2015:22 "Wizard Simulator 20XX" * Solve 2015:23 "Opening the Turing Lock" * Solve 2015:25 "Let it Snow" Wrote p2rc and rc2p just for academic purposes. Puzzles could be solved anyway. * Solve 2015:24 "Hangs in the Balance" --------- Co-authored-by: Anders Englöf Ytterström <anders@playmaker.ai>
151 lines
3.6 KiB
Python
151 lines
3.6 KiB
Python
import random
|
|
import re
|
|
from math import inf
|
|
|
|
from solutions import BaseSolution
|
|
|
|
C = {
|
|
"M": 53,
|
|
"D": 73,
|
|
"S": 113,
|
|
"P": 173,
|
|
"R": 229,
|
|
}
|
|
|
|
D = {
|
|
"S": 6,
|
|
"P": 6,
|
|
"R": 5,
|
|
}
|
|
|
|
E = {
|
|
"P": 3,
|
|
"R": 101,
|
|
"S": 7,
|
|
}
|
|
|
|
|
|
class Solution(BaseSolution):
|
|
input_file = "22.txt"
|
|
|
|
def __str__(self):
|
|
return "Day 22: Wizard Simulator 20XX"
|
|
|
|
def solve(self, pi):
|
|
o = self._solve(pi)
|
|
return o[0]
|
|
|
|
def solve_again(self, pi):
|
|
o = self._solve(pi)
|
|
return o[1]
|
|
|
|
def parse_input(self, data):
|
|
return data.strip()
|
|
|
|
def _solve(self, data):
|
|
p12 = []
|
|
boss = re.findall(r"\d+", data)
|
|
shp, smp = 50, 500
|
|
for hd in [False, True]:
|
|
x = 100_000
|
|
l = inf
|
|
for _i in range(x):
|
|
bhp, bd = [int(v) for v in boss]
|
|
t, ms = 0, 0
|
|
hp, mp = shp, smp
|
|
e = {"S": 0, "P": 0, "R": 0}
|
|
while hp > 0 and bhp > 0 and mp > 0:
|
|
if hd and t % 2 == 0:
|
|
hp -= 1
|
|
if hp == 0:
|
|
break
|
|
b = {"d": bd, "e": 0}
|
|
p = {"e": 0}
|
|
if e["P"] > 0:
|
|
e["P"] -= 1
|
|
bhp -= E["P"]
|
|
if bhp <= 0:
|
|
break
|
|
if e["R"] > 0:
|
|
e["R"] -= 1
|
|
mp += E["R"]
|
|
if e["S"] > 0:
|
|
e["S"] -= 1
|
|
p["e"] += E["S"]
|
|
if t % 2 == 0:
|
|
a = self._guess(mp, e)
|
|
if a in "RSP":
|
|
e[a] = D[a]
|
|
dp, db = self._turn(t, p, b, a)
|
|
mp -= C[a]
|
|
ms += C[a]
|
|
else:
|
|
dp, db = self._turn(t, p, b)
|
|
hp += dp
|
|
bhp += db
|
|
t += 1
|
|
if bhp <= 0 and mp >= 0:
|
|
l = min(l, ms)
|
|
p12.append(l)
|
|
assert p12[0] == 953
|
|
assert p12[1] == 1289
|
|
return p12
|
|
|
|
@staticmethod
|
|
def _guess(mp, e):
|
|
v = False
|
|
while not v:
|
|
a = random.choice("MDPRS")
|
|
match a:
|
|
case "S" | "P" | "R":
|
|
v = e[a] == 0
|
|
case _:
|
|
v = True
|
|
return a
|
|
|
|
@staticmethod
|
|
def _turn(t, p, b, a=None):
|
|
"""Take turns
|
|
|
|
>>> Solution._turn(1, {}, {"d": 5})
|
|
(-5, 0)
|
|
>>> Solution._turn(1, {}, {"d": 5, "e": -2})
|
|
(-5, -2)
|
|
>>> Solution._turn(1, {"e": 7}, {"d": 5})
|
|
(-1, 0)
|
|
>>> Solution._turn(2, {}, {}, "M")
|
|
(0, -4)
|
|
>>> Solution._turn(2, {}, {}, "D")
|
|
(2, -2)
|
|
>>> Solution._turn(2, {}, {}, "S")
|
|
(0, 0)
|
|
>>> Solution._turn(2, {}, {}, "P")
|
|
(0, 0)
|
|
>>> Solution._turn(2, {}, {}, "R")
|
|
(0, 0)
|
|
"""
|
|
ped = p.get("e", 0)
|
|
bed = b.get("e", 0)
|
|
if t % 2 == 1:
|
|
return min(ped - b["d"], -1), 0 + bed
|
|
else:
|
|
match a:
|
|
case "D":
|
|
return 2, -2
|
|
case "M":
|
|
return 0, -4
|
|
case "S":
|
|
return 0, 0
|
|
case "R":
|
|
return 0, 0
|
|
case "P":
|
|
return 0, 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import doctest
|
|
|
|
doctest.testmod()
|
|
|
|
solution = Solution()
|
|
solution.show_results()
|