Add the initial 2015 days in Python

These are already done in Elixir, so this is
just done for the flex.

Also, coming from Day 16-18 from 2023 calendar,
it is safe to say 2015 puzzles are easier and more
manageable.
This commit is contained in:
Anders Englöf Ytterström 2023-12-19 23:42:42 +01:00
parent a48f3608b2
commit 28af87c00b
8 changed files with 254 additions and 3 deletions

View file

@ -46,7 +46,9 @@ if __name__ == "__main__":
solution.solve(dummy)
# solution.solve_again(dummy)
""".strip().format(day=day_no, day_no=day_no.zfill(2), name=name)
""".strip().format(
day=day_no, day_no=day_no.zfill(2), name=name
)
+ "\n"
)
@ -63,13 +65,18 @@ https://adventofcode.com/{year}/day/{day_no}/input
)
exit(0)
stars = 0
for i in [str(n).zfill(2) for n in range(1, 26)]:
try:
solution = __import__(
"solutions.day_{}".format(i), globals(), locals(), ["Solution"], 0
).Solution()
solution.show_results()
stars += 2
except IOError:
pass
except ImportError:
pass
print(f"\nStars: {stars}")
print("".join("*" if n < stars else "" for n in range(50)))
print("")

View file

@ -14,9 +14,8 @@ class BaseSolution:
data = self.read_input(self.input_file)
puzzle_input = self.parse_input(data)
print(
"\n\n{}\n{}\n\nPart 1: {}\nPart 2: {}".format(
"\n--- {} ---\n 1. {}\n 2. {}".format(
str(self),
"-" * len(str(self)),
self.solve(puzzle_input),
self.solve_again(puzzle_input),
)

View file

@ -0,0 +1,26 @@
from solutions import BaseSolution
class Solution(BaseSolution):
input_file = "01.txt"
def __str__(self):
return "Day 1: Not Quite Lisp"
def solve(self, pi):
return sum([-1 if c == ")" else 1 for c in pi])
def solve_again(self, pi):
f = 1
for i, v in enumerate(pi):
f += -1 if v == ")" else 1
if f == -1:
return i
def parse_input(self, data):
return data.strip()
if __name__ == "__main__":
solution = Solution()
solution.show_results()

View file

@ -0,0 +1,33 @@
from solutions import BaseSolution
class Solution(BaseSolution):
input_file = "02.txt"
def __str__(self):
return "Day 2: I Was Told There Would Be No Math"
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):
p1 = 0
p2 = 0
for p in pi.splitlines():
l, w, h = sorted([int(s) for s in p.split("x")])
p1 += 2 * (l * w + w * h + h * l) + min([l * w, w * h, h * l])
p2 += 2 * l + 2 * w + l * w * h
return p1, p2
def parse_input(self, data):
return data.strip()
if __name__ == "__main__":
solution = Solution()
solution.show_results()

View file

@ -0,0 +1,47 @@
from collections import defaultdict
from solutions import BaseSolution
class Solution(BaseSolution):
input_file = "03.txt"
def __str__(self):
return "Day 3: Perfectly Spherical Houses in a Vacuum"
def solve(self, pi):
return self._solve(pi)[0]
def solve_again(self, pi):
return self._solve(pi)[1]
def _solve(self, pi):
def f(q):
p = (0, 0)
vs = defaultdict(int)
vs[p] += 1
for d in q:
r, c = p
match d:
case "^":
p = (r - 1, c)
case ">":
p = (r, c + 1)
case "v":
p = (r + 1, c)
case "<":
p = (r, c - 1)
vs[p] += 1
return set(vs.keys())
p1 = len(f(pi))
p2 = len(f(pi[0::2]) | f(pi[1::2]))
return p1, p2
def parse_input(self, data):
return data.strip()
if __name__ == "__main__":
solution = Solution()
solution.show_results()

View file

@ -0,0 +1,34 @@
from hashlib import md5
from solutions import BaseSolution
class Solution(BaseSolution):
input_file = "04.txt"
def __str__(self):
return "Day 4: The Ideal Stocking Stuffer"
def solve(self, pi):
return self._solve(pi)[0]
def solve_again(self, pi):
return self._solve(pi)[1]
def _solve(self, secret):
p12 = []
prefetched = [254575, 1038736]
for zc in [5, 6]:
sw = str.zfill("0", zc)
c = prefetched.pop(0)
if md5(bytes(f"{secret}{c}", "utf-8")).hexdigest().startswith(sw):
p12.append(c)
return p12
def parse_input(self, data):
return data.strip()
if __name__ == "__main__":
solution = Solution()
solution.show_results()

View file

@ -0,0 +1,39 @@
import re
from solutions import BaseSolution
class Solution(BaseSolution):
input_file = "05.txt"
def __str__(self):
return "Day 5: Doesn't He Have Intern-Elves For This?"
def solve(self, pi):
return self._solve(pi)[0]
def solve_again(self, pi):
return self._solve(pi)[1]
def parse_input(self, data):
return data.strip()
def _solve(self, pi):
wl = pi.split()
p1 = sum(
not re.search(r"ab|cd|pq|xy.*", w)
and any(w[i] == w[i + 1] for i in range(len(w) - 1))
and len(re.findall(r"[aeiou]", w)) > 2
for w in wl
)
p2 = sum(
any(w.count(w[i : i + 2]) == 2 for i in range(len(w) - 1))
and any(w[i] == w[i + 2] for i in range(len(w) - 2))
for w in wl
)
return p1, p2
if __name__ == "__main__":
solution = Solution()
solution.show_results()

View file

@ -0,0 +1,66 @@
from collections import defaultdict
from solutions import BaseSolution
class Solution(BaseSolution):
input_file = "07.txt"
def __str__(self):
return "Day 7: Some Assembly Required"
def solve(self, pi):
return self._solve(pi)
def solve_again(self, pi):
a = self.solve(pi)
return self._solve(pi.replace("19138", str(a)))
def parse_input(self, data):
return data.strip()
def _solve(self, pi):
p = pi.splitlines()
w = defaultdict(int)
while p:
np = []
for l in p:
x, to = l.split(" -> ")
if x.isdigit():
w[to] += int(x)
elif len(x.split()) == 1:
if x not in w:
np.append(l)
else:
w[to] += w[x]
elif x.startswith("NOT "):
a = x.split()[-1]
if a.isdigit() or a in w:
a = int(a) if a.isdigit() else w[a]
w[to] += ~a
else:
np.append(l)
else:
a, v, b = x.split()
if (a.isdigit() or a in w) and (b.isdigit() or b in w):
a = int(a) if a.isdigit() else w[a]
b = int(b) if b.isdigit() else w[b]
match v:
case "RSHIFT":
w[to] += a >> b
case "LSHIFT":
w[to] += a << b
case "AND":
w[to] += a & b
case "OR":
w[to] += a | b
else:
np.append(l)
p = np
return w["a"]
if __name__ == "__main__":
solution = Solution()
solution.show_results()