2015, day 16-25 (first completed calendar!) (#11)
* 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>
This commit is contained in:
parent
b6e048e4a7
commit
5a5e843129
13 changed files with 857 additions and 53 deletions
|
|
@ -26,65 +26,29 @@ class Solution(BaseSolution):
|
|||
def __str__(self):
|
||||
return "Day {day}: {name}"
|
||||
|
||||
def solve(self, pi):
|
||||
return pi
|
||||
|
||||
def solve_again(self, pi):
|
||||
return pi
|
||||
|
||||
def parse_input(self, data):
|
||||
return data.strip()
|
||||
|
||||
def solve(self, puzzle_input):
|
||||
return True
|
||||
|
||||
def solve_again(self, puzzle_input):
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
solution = Solution()
|
||||
solution.show_results()
|
||||
""".strip().format(
|
||||
day=day_no, day_no=day_no.zfill(2), name=name
|
||||
)
|
||||
# solution.show_results()
|
||||
|
||||
dummy = \"\"\"
|
||||
replace me
|
||||
\"\"\".strip()
|
||||
|
||||
solution.solve(dummy)
|
||||
# solution.solve_again(dummy)
|
||||
""".strip().format(day=day_no, day_no=day_no.zfill(2), name=name)
|
||||
+ "\n"
|
||||
)
|
||||
print(f"- creating tests/test_day_{day_no.zfill(2)}.py")
|
||||
with open("tests/test_day_{}.py".format(day_no.zfill(2)), "w") as t:
|
||||
t.write(
|
||||
"""
|
||||
import unittest
|
||||
|
||||
from solutions.day_{day_no} import Solution
|
||||
|
||||
|
||||
class Day{day_no}TestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.solution = Solution()
|
||||
self.puzzle_input = self.solution.parse_input(
|
||||
\"\"\"
|
||||
<REPLACE ME>
|
||||
\"\"\"
|
||||
)
|
||||
|
||||
def test_parse_puzzle_input(self):
|
||||
data = \"\"\"
|
||||
<REPLACE ME>
|
||||
\"\"\"
|
||||
assert self.solution.parse_input(data) == "<REPLACE ME>"
|
||||
|
||||
# def test_solve_first_part(self):
|
||||
# assert self.solution.solve(self.puzzle_input) == True
|
||||
|
||||
# def test_solve_second_part(self):
|
||||
# assert self.solution.solve_again(self.puzzle_input) == True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
""".strip().format(
|
||||
day_no=day_no.zfill(2)
|
||||
)
|
||||
+ "\n"
|
||||
)
|
||||
print(f"- creating empty inputs/{day_no.zfill(2)}.txt")
|
||||
with open("inputs/{}.txt".format(day_no.zfill(2)), "w") as i:
|
||||
i.write("")
|
||||
|
||||
print(
|
||||
f"""
|
||||
|
|
|
|||
50
2015-python/solutions/day_06.py
Normal file
50
2015-python/solutions/day_06.py
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
import re
|
||||
from solutions import BaseSolution
|
||||
from collections import defaultdict
|
||||
|
||||
|
||||
class Solution(BaseSolution):
|
||||
input_file = "06.txt"
|
||||
|
||||
def __str__(self):
|
||||
return "Day 6: Probably a Fire Hazard"
|
||||
|
||||
def parse_input(self, data):
|
||||
return data.strip()
|
||||
|
||||
def solve(self, puzzle_input):
|
||||
m = defaultdict(bool)
|
||||
for ase in puzzle_input.splitlines():
|
||||
p = re.match(r"^(.+) (\d+),(\d+)\D+(\d+),(\d+)", ase).groups()
|
||||
a, sx, sy, ex, ey = p
|
||||
for r in range(int(sy), int(ey) + 1):
|
||||
for c in range(int(sx), int(ex) + 1):
|
||||
match a:
|
||||
case "toggle":
|
||||
m[(r, c)] = not m[(r, c)]
|
||||
case "turn on":
|
||||
m[(r, c)] = True
|
||||
case "turn off":
|
||||
m[(r, c)] = False
|
||||
return sum(m.values())
|
||||
|
||||
def solve_again(self, puzzle_input):
|
||||
m = defaultdict(int)
|
||||
for ase in puzzle_input.splitlines():
|
||||
p = re.match(r"^(.+) (\d+),(\d+)\D+(\d+),(\d+)", ase).groups()
|
||||
a, sx, sy, ex, ey = p
|
||||
for r in range(int(sy), int(ey) + 1):
|
||||
for c in range(int(sx), int(ex) + 1):
|
||||
match a:
|
||||
case "toggle":
|
||||
m[(r, c)] += 2
|
||||
case "turn on":
|
||||
m[(r, c)] += 1
|
||||
case "turn off":
|
||||
m[(r, c)] = max(m[(r, c)] - 1, 0)
|
||||
return sum(m.values())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
solution = Solution()
|
||||
solution.show_results()
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import re
|
||||
|
||||
from solutions import BaseSolution
|
||||
|
||||
|
||||
|
|
@ -20,8 +21,8 @@ class Solution(BaseSolution):
|
|||
|
||||
def solve_again(self, puzzle_input):
|
||||
def lendiff(line):
|
||||
encoded = f'"{line.replace("\\", "\\\\").replace('"', '\\"')}"'
|
||||
return len(encoded) - len(line)
|
||||
encoded = line.replace("\\", "\\\\").replace('"', '\\"')
|
||||
return len(encoded) + 2 - len(line)
|
||||
|
||||
return sum(map(lendiff, puzzle_input))
|
||||
|
||||
|
|
|
|||
56
2015-python/solutions/day_16.py
Normal file
56
2015-python/solutions/day_16.py
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import re
|
||||
from collections import defaultdict
|
||||
|
||||
from solutions import BaseSolution
|
||||
|
||||
S = {
|
||||
"children": 3,
|
||||
"cats": 7,
|
||||
"samoyeds": 2,
|
||||
"pomeranians": 3,
|
||||
"akitas": 0,
|
||||
"vizslas": 0,
|
||||
"goldfish": 5,
|
||||
"trees": 3,
|
||||
"cars": 2,
|
||||
"perfumes": 1,
|
||||
}
|
||||
|
||||
|
||||
class Solution(BaseSolution):
|
||||
input_file = "16.txt"
|
||||
|
||||
def __str__(self):
|
||||
return "Day 16: Aunt Sue"
|
||||
|
||||
def parse_input(self, data):
|
||||
return data.strip()
|
||||
|
||||
def solve(self, puzzle_input):
|
||||
s = defaultdict(int)
|
||||
for i, l in enumerate(puzzle_input.splitlines(), 1):
|
||||
for kv in re.findall(r"\w+: \d+", l):
|
||||
k, v = kv.split(": ")
|
||||
v = int(v)
|
||||
s[i] += 1 if k in S and S[k] == v else 0
|
||||
return max(s.items(), key=lambda x: x[1])[0]
|
||||
|
||||
def solve_again(self, puzzle_input):
|
||||
s = defaultdict(int)
|
||||
for i, l in enumerate(puzzle_input.splitlines(), 1):
|
||||
for kv in re.findall(r"\w+: \d+", l):
|
||||
k, v = kv.split(": ")
|
||||
v = int(v)
|
||||
match k:
|
||||
case "cats" | "trees":
|
||||
s[i] += 1 if k in S and S[k] < v else 0
|
||||
case "pomeranians" | "goldfish":
|
||||
s[i] += 1 if k in S and S[k] > v else 0
|
||||
case _:
|
||||
s[i] += 1 if k in S and S[k] == v else 0
|
||||
return max(s.items(), key=lambda x: x[1])[0]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
solution = Solution()
|
||||
solution.show_results()
|
||||
36
2015-python/solutions/day_17.py
Normal file
36
2015-python/solutions/day_17.py
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
from collections import defaultdict
|
||||
from itertools import combinations
|
||||
|
||||
from solutions import BaseSolution
|
||||
|
||||
|
||||
class Solution(BaseSolution):
|
||||
input_file = "17.txt"
|
||||
|
||||
def __str__(self):
|
||||
return "Day 17: No Such Thing as Too Much"
|
||||
|
||||
def parse_input(self, data):
|
||||
return data.strip()
|
||||
|
||||
def solve(self, puzzle_input, g=150):
|
||||
return self._solve(puzzle_input, g)[0]
|
||||
|
||||
def solve_again(self, puzzle_input, g=150):
|
||||
return self._solve(puzzle_input, g)[1]
|
||||
|
||||
def _solve(self, puzzle_input, g=150):
|
||||
buckets = sorted(list(map(int, puzzle_input.split())), reverse=True)
|
||||
t = 0
|
||||
r = defaultdict(int)
|
||||
for i in range(len(buckets)):
|
||||
for c in combinations(buckets, i):
|
||||
if sum(c) == g:
|
||||
t += 1
|
||||
r[i] += 1
|
||||
return t, min(r.items(), key=lambda kv: kv[0])[1]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
solution = Solution()
|
||||
solution.show_results()
|
||||
79
2015-python/solutions/day_18.py
Normal file
79
2015-python/solutions/day_18.py
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
from collections import defaultdict
|
||||
from solutions import BaseSolution
|
||||
|
||||
|
||||
N = [
|
||||
(-1, -1),
|
||||
(-1, 0),
|
||||
(-1, 1),
|
||||
(0, -1),
|
||||
(0, 1),
|
||||
(1, -1),
|
||||
(1, 0),
|
||||
(1, 1),
|
||||
]
|
||||
|
||||
|
||||
class Solution(BaseSolution):
|
||||
input_file = "18.txt"
|
||||
|
||||
def __str__(self):
|
||||
return "Day 18: Like a GIF For Your Yard"
|
||||
|
||||
def parse_input(self, data):
|
||||
return data.strip()
|
||||
|
||||
def solve(self, data):
|
||||
m = defaultdict(bool)
|
||||
rows = data.split()
|
||||
h = len(rows)
|
||||
w = len(rows[0])
|
||||
for r in range(h):
|
||||
for c in range(w):
|
||||
m[(r, c)] = 1 if rows[r][c] == "#" else 0
|
||||
for _ in range(100):
|
||||
nm = defaultdict(bool)
|
||||
for r in range(h):
|
||||
for c in range(w):
|
||||
n = sum(m[(r + nr, c + nc)] for nr, nc in N)
|
||||
match m[(r, c)]:
|
||||
case 1:
|
||||
nm[(r, c)] = n in (2, 3)
|
||||
case 0:
|
||||
nm[(r, c)] = n == 3
|
||||
m = nm
|
||||
return sum(m.values())
|
||||
|
||||
def solve_again(self, data):
|
||||
m = defaultdict(bool)
|
||||
rows = data.split()
|
||||
h = len(rows)
|
||||
w = len(rows[0])
|
||||
for r in range(h):
|
||||
for c in range(w):
|
||||
m[(r, c)] = 1 if rows[r][c] == "#" else 0
|
||||
m[(0, 0)] = True
|
||||
m[(99, 0)] = True
|
||||
m[(99, 99)] = True
|
||||
m[(0, 99)] = True
|
||||
for _ in range(100):
|
||||
nm = defaultdict(bool)
|
||||
for r in range(h):
|
||||
for c in range(w):
|
||||
if (r, c) in [(0, 0), (99, 0), (99, 99), (0, 99)]:
|
||||
nm[(r, c)] = True
|
||||
continue
|
||||
n = sum(m[(r + nr, c + nc)] for nr, nc in N)
|
||||
match m[(r, c)]:
|
||||
case 1:
|
||||
nm[(r, c)] = n in (2, 3)
|
||||
case 0:
|
||||
nm[(r, c)] = n == 3
|
||||
m = nm
|
||||
return sum(m.values())
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
solution = Solution()
|
||||
solution.show_results()
|
||||
51
2015-python/solutions/day_19.py
Normal file
51
2015-python/solutions/day_19.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
from collections import defaultdict
|
||||
from solutions import BaseSolution
|
||||
import re
|
||||
from random import shuffle, choice
|
||||
|
||||
|
||||
class Solution(BaseSolution):
|
||||
input_file = "19.txt"
|
||||
|
||||
def __str__(self):
|
||||
return "Day 19: Medicine for Rudolph"
|
||||
|
||||
def solve(self, pi):
|
||||
ml, s = pi.split("\n\n")
|
||||
o = set()
|
||||
for l in ml.splitlines():
|
||||
k, v = l.split(" => ")
|
||||
for mo in re.finditer(k, s):
|
||||
a, b = mo.span()
|
||||
o.add(s[:a] + v + s[b:])
|
||||
return len(o)
|
||||
|
||||
def solve_again(self, pi):
|
||||
m = {}
|
||||
ml, e = pi.split("\n\n")
|
||||
for l in ml.splitlines():
|
||||
k, v = l.split(" => ")
|
||||
m[v] = k
|
||||
p2 = 0
|
||||
while p2 == 0:
|
||||
s = e
|
||||
c = 0
|
||||
os = ""
|
||||
keys = list(m.keys())
|
||||
shuffle(keys)
|
||||
while os != s:
|
||||
os = s
|
||||
for k in keys:
|
||||
while k in s:
|
||||
c += s.count(k)
|
||||
s = s.replace(k, m[k])
|
||||
p2 = int(s == "e") * c
|
||||
return p2
|
||||
|
||||
def parse_input(self, data):
|
||||
return data.strip()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
solution = Solution()
|
||||
solution.show_results()
|
||||
51
2015-python/solutions/day_20.py
Normal file
51
2015-python/solutions/day_20.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
from collections import defaultdict
|
||||
from solutions import BaseSolution
|
||||
|
||||
|
||||
class Solution(BaseSolution):
|
||||
input_file = "20.txt"
|
||||
|
||||
def __str__(self):
|
||||
return "Day 20: Infinite Elves and Infinite Houses"
|
||||
|
||||
def solve(self, pi):
|
||||
S = 36_000_000
|
||||
# hn = 831601
|
||||
# x1 = defaultdict(int)
|
||||
# for i in range(1, hn):
|
||||
# for n in range(0, hn, i):
|
||||
# if n == 0:
|
||||
# continue
|
||||
# x1[n] += i * 10
|
||||
# for k, v in x1.items():
|
||||
# if v >= S:
|
||||
# print(k, v)
|
||||
hn = 885000
|
||||
hc = 50
|
||||
x2 = defaultdict(int)
|
||||
for i in range(1, hn):
|
||||
for n in range(0, hc * i + 1, i):
|
||||
if n == 0:
|
||||
continue
|
||||
x2[n] += i * 11
|
||||
# p1 = max(x1.items(), key=lambda y: y[1])[0]
|
||||
p2 = min(filter(lambda x: x[1] >= S, x2.items()), key=lambda y: y[0])[0]
|
||||
return 0, p2
|
||||
|
||||
def solve_again(self, pi):
|
||||
return pi
|
||||
|
||||
def parse_input(self, data):
|
||||
return data.strip()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
solution = Solution()
|
||||
# solution.show_results()
|
||||
|
||||
dummy = """
|
||||
replace me
|
||||
""".strip()
|
||||
|
||||
print(solution.solve(dummy))
|
||||
# solution.solve_again(dummy)
|
||||
100
2015-python/solutions/day_21.py
Normal file
100
2015-python/solutions/day_21.py
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
import re
|
||||
from itertools import product
|
||||
from math import inf
|
||||
|
||||
from solutions import BaseSolution
|
||||
|
||||
SHOP = [
|
||||
[
|
||||
("Dagger", 8, 4, 0),
|
||||
("Shortsword", 10, 5, 0),
|
||||
("Warhammer", 25, 6, 0),
|
||||
("Longsword", 40, 7, 0),
|
||||
("Greataxe", 74, 8, 0),
|
||||
],
|
||||
[
|
||||
("No armor", 0, 0, 0),
|
||||
("Leather", 13, 0, 1),
|
||||
("Chainmail", 31, 0, 2),
|
||||
("Splintmail", 53, 0, 3),
|
||||
("Bandedmail", 75, 0, 4),
|
||||
("Platemail", 102, 0, 5),
|
||||
],
|
||||
[
|
||||
("No ring", 0, 0, 0),
|
||||
("Damage +1", 25, 1, 0),
|
||||
("Damage +2", 50, 2, 0),
|
||||
("Damage +3", 100, 3, 0),
|
||||
("Defense +1", 20, 0, 1),
|
||||
("Defense +2", 40, 0, 2),
|
||||
("Defense +3", 80, 0, 3),
|
||||
("Damage +1 & Damage +2", 75, 3, 0),
|
||||
("Damage +1 & Damage +3", 125, 4, 0),
|
||||
("Damage +1 & Defense +1", 45, 1, 1),
|
||||
("Damage +1 & Defense +2", 65, 1, 2),
|
||||
("Damage +1 & Defense +3", 105, 1, 3),
|
||||
("Damage +2 & Damage +3", 150, 5, 0),
|
||||
("Damage +2 & Defense +1", 70, 2, 1),
|
||||
("Damage +2 & Defense +2", 90, 2, 2),
|
||||
("Damage +2 & Defense +3", 130, 2, 3),
|
||||
("Damage +3 & Defense +1", 120, 3, 1),
|
||||
("Damage +3 & Defense +2", 140, 3, 2),
|
||||
("Damage +3 & Defense +3", 180, 3, 3),
|
||||
("Defense +1 & Defense +2", 60, 0, 3),
|
||||
("Defense +1 & Defense +3", 100, 0, 4),
|
||||
("Defense +2 & Defense +3", 120, 0, 5),
|
||||
],
|
||||
]
|
||||
|
||||
|
||||
class Solution(BaseSolution):
|
||||
input_file = "21.txt"
|
||||
|
||||
def __str__(self):
|
||||
return "Day 21: RPG 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, pi):
|
||||
boss = re.findall(r"\d+", pi)
|
||||
l = inf
|
||||
m = 0
|
||||
for ph, pd, pa, c in self._gearup():
|
||||
bh, bd, ba = [int(v) for v in boss]
|
||||
while bh > 0 and ph > 0:
|
||||
bh -= max(1, pd - ba)
|
||||
if bh <= 0:
|
||||
break
|
||||
ph -= max(1, bd - pa)
|
||||
if ph > 0:
|
||||
l = min(l, c)
|
||||
else:
|
||||
m = max(m, c)
|
||||
return l, m
|
||||
|
||||
def _gearup(self):
|
||||
g = []
|
||||
for w, a, r in product(*SHOP):
|
||||
g.append(
|
||||
(
|
||||
100,
|
||||
sum([w[2], a[2], r[2]]),
|
||||
sum([w[3], a[3], r[3]]),
|
||||
sum([w[1], a[1], r[1]]),
|
||||
)
|
||||
)
|
||||
return g
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
solution = Solution()
|
||||
solution.show_results()
|
||||
151
2015-python/solutions/day_22.py
Normal file
151
2015-python/solutions/day_22.py
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
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()
|
||||
65
2015-python/solutions/day_23.py
Normal file
65
2015-python/solutions/day_23.py
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
from solutions import BaseSolution
|
||||
|
||||
|
||||
class Solution(BaseSolution):
|
||||
input_file = "23.txt"
|
||||
|
||||
def __str__(self):
|
||||
return "Day 23: Opening the Turing Lock"
|
||||
|
||||
def _solve(self, pi):
|
||||
p12 = []
|
||||
for a in [0, 1]:
|
||||
m = {
|
||||
"a": a,
|
||||
"b": 0,
|
||||
}
|
||||
p = [l.split() for l in pi.splitlines()]
|
||||
i = 0
|
||||
while i < len(p):
|
||||
v, rv, *a = p[i]
|
||||
rv = rv.split(",")[0]
|
||||
match v:
|
||||
case "hlf":
|
||||
m[rv] //= 2
|
||||
i += 1
|
||||
case "tpl":
|
||||
m[rv] *= 3
|
||||
i += 1
|
||||
case "inc":
|
||||
m[rv] += 1
|
||||
i += 1
|
||||
case "jmp":
|
||||
i += int(rv)
|
||||
case "jie":
|
||||
i += int(a[0]) if int(m[rv]) % 2 == 0 else 1
|
||||
case "jio":
|
||||
i += int(a[0]) if int(m[rv]) == 1 else 1
|
||||
p12.append(m["b"])
|
||||
return p12
|
||||
|
||||
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()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
solution = Solution()
|
||||
solution.show_results()
|
||||
|
||||
dummy = """
|
||||
inc a
|
||||
jio a, +2
|
||||
tpl a
|
||||
inc a
|
||||
""".strip()
|
||||
|
||||
# solution.solve(dummy)
|
||||
# solution.solve_again(dummy)
|
||||
50
2015-python/solutions/day_24.py
Normal file
50
2015-python/solutions/day_24.py
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
import re
|
||||
from itertools import combinations
|
||||
from math import prod
|
||||
|
||||
from solutions import BaseSolution
|
||||
|
||||
|
||||
class Solution(BaseSolution):
|
||||
input_file = "24.txt"
|
||||
|
||||
def __str__(self):
|
||||
return "Day 24: Hangs in the Balance"
|
||||
|
||||
def solve(self, pi):
|
||||
o = self._solve(pi)
|
||||
return o[0]
|
||||
|
||||
def solve_again(self, pi):
|
||||
o = self._solve(pi)
|
||||
return o[1]
|
||||
|
||||
def _solve(self, pi):
|
||||
p12 = []
|
||||
for g in [3, 4]:
|
||||
w = [int(s) for s in re.findall(r"\d+", pi)]
|
||||
gs = sum(w) // g
|
||||
c = []
|
||||
for r in range(len(w)):
|
||||
for n in combinations(w, r=r):
|
||||
if sum(n) == gs:
|
||||
c.append(n)
|
||||
if c:
|
||||
break
|
||||
p12.append(min(map(prod, c)))
|
||||
return p12
|
||||
|
||||
def parse_input(self, data):
|
||||
return data.strip()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
solution = Solution()
|
||||
solution.show_results()
|
||||
|
||||
dummy = """
|
||||
1,2,3,4,5,7,8,9,10,11
|
||||
""".strip()
|
||||
|
||||
solution.solve(dummy)
|
||||
# solution.solve_again(dummy)
|
||||
150
2015-python/solutions/day_25.py
Normal file
150
2015-python/solutions/day_25.py
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
import re
|
||||
|
||||
from solutions import BaseSolution
|
||||
|
||||
|
||||
class Solution(BaseSolution):
|
||||
input_file = "25.txt"
|
||||
|
||||
def __str__(self):
|
||||
return "Day 25: Let It Snow"
|
||||
|
||||
def solve(self, pi):
|
||||
r, c = [int(s) - 1 for s in re.findall(r"\d+", pi)]
|
||||
v = 20151125
|
||||
seen = set()
|
||||
e = rc2p(r, c)
|
||||
t = 0
|
||||
while v not in seen:
|
||||
seen.add(v)
|
||||
v = v * 252533 % 33554393
|
||||
t += 1
|
||||
for _ in range(e % t - 1):
|
||||
v = v * 252533 % 33554393
|
||||
assert v == 9132360
|
||||
return v
|
||||
|
||||
def solve_again(self, pi):
|
||||
return "God jul!"
|
||||
|
||||
def parse_input(self, data):
|
||||
return data.strip()
|
||||
|
||||
|
||||
def p2rc(p):
|
||||
"""
|
||||
Get row and column for a storage position
|
||||
|
||||
>>> p2rc(1)
|
||||
(0, 0)
|
||||
>>> p2rc(2)
|
||||
(1, 0)
|
||||
>>> p2rc(3)
|
||||
(0, 1)
|
||||
>>> p2rc(4)
|
||||
(2, 0)
|
||||
>>> p2rc(5)
|
||||
(1, 1)
|
||||
>>> p2rc(6)
|
||||
(0, 2)
|
||||
>>> p2rc(7)
|
||||
(3, 0)
|
||||
>>> p2rc(8)
|
||||
(2, 1)
|
||||
>>> p2rc(9)
|
||||
(1, 2)
|
||||
>>> p2rc(10)
|
||||
(0, 3)
|
||||
>>> p2rc(11)
|
||||
(4, 0)
|
||||
>>> p2rc(12)
|
||||
(3, 1)
|
||||
>>> p2rc(13)
|
||||
(2, 2)
|
||||
>>> p2rc(14)
|
||||
(1, 3)
|
||||
>>> p2rc(15)
|
||||
(0, 4)
|
||||
>>> p2rc(16)
|
||||
(5, 0)
|
||||
>>> p2rc(17)
|
||||
(4, 1)
|
||||
>>> p2rc(18)
|
||||
(3, 2)
|
||||
>>> p2rc(19)
|
||||
(2, 3)
|
||||
>>> p2rc(20)
|
||||
(1, 4)
|
||||
>>> p2rc(21)
|
||||
(0, 5)
|
||||
"""
|
||||
v = 0
|
||||
i = 0
|
||||
while v < p:
|
||||
i += 1
|
||||
v = sum(range(i + 1))
|
||||
|
||||
r, c = 0, i - 1
|
||||
for _ in range(v - p):
|
||||
r += 1
|
||||
c -= 1
|
||||
return (r, c)
|
||||
|
||||
|
||||
def rc2p(r, c):
|
||||
"""
|
||||
Get storage position for coordinate row R, column C
|
||||
|
||||
>>> rc2p(0, 0)
|
||||
1
|
||||
>>> rc2p(1, 0)
|
||||
2
|
||||
>>> rc2p(0, 1)
|
||||
3
|
||||
>>> rc2p(2, 0)
|
||||
4
|
||||
>>> rc2p(1, 1)
|
||||
5
|
||||
>>> rc2p(0, 2)
|
||||
6
|
||||
>>> rc2p(3, 0)
|
||||
7
|
||||
>>> rc2p(2, 1)
|
||||
8
|
||||
>>> rc2p(1, 2)
|
||||
9
|
||||
>>> rc2p(0, 3)
|
||||
10
|
||||
>>> rc2p(4, 0)
|
||||
11
|
||||
>>> rc2p(3, 1)
|
||||
12
|
||||
>>> rc2p(2, 2)
|
||||
13
|
||||
>>> rc2p(1, 3)
|
||||
14
|
||||
>>> rc2p(0, 4)
|
||||
15
|
||||
>>> rc2p(5, 0)
|
||||
16
|
||||
>>> rc2p(4, 1)
|
||||
17
|
||||
>>> rc2p(3, 2)
|
||||
18
|
||||
>>> rc2p(2, 3)
|
||||
19
|
||||
>>> rc2p(1, 4)
|
||||
20
|
||||
>>> rc2p(0, 5)
|
||||
21
|
||||
"""
|
||||
return sum(range(r + c + 1)) + c + 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
|
||||
doctest.testmod()
|
||||
|
||||
solution = Solution()
|
||||
solution.show_results()
|
||||
Loading…
Add table
Reference in a new issue