Compare commits

...

5 Commits

Author SHA1 Message Date
288a0809ff Solve 2025 day 7 2026-02-16 12:23:56 -05:00
42e0c68d93 Implement 2025 day 6 2026-02-16 11:51:21 -05:00
867a7ed2df Solve 2025 day 5 2026-01-11 12:12:55 -05:00
df0682e989 Solve 2025 day 3 and 4 2026-01-11 10:33:21 -05:00
e5421854a9 Do day 3 and 4 for 2025 2025-12-26 20:18:44 -05:00
8 changed files with 257 additions and 1 deletions

2
.gitignore vendored
View File

@@ -4,6 +4,8 @@
__pycache__/ __pycache__/
*.py[cod] *.py[cod]
*$py.class *$py.class
.python-version
uv.lock
# C extensions # C extensions
*.so *.so

34
2025/d03.py Normal file
View File

@@ -0,0 +1,34 @@
from lib import get_data
data = get_data(__file__)
def max_joltage(xs: str, target_len: int) -> int:
def dynamic(xs: str) -> dict[int, str]:
if len(xs) == 0:
return {0: ""}
rs = dynamic(xs[1:])
for i in range(target_len, 0, -1):
if not (i - 1) in rs:
continue
nv = int(xs[0] + rs[i - 1])
if not i in rs:
rs[i] = str(nv)
elif nv > int(rs[i]):
rs[i] = str(nv)
return rs
rs = dynamic(xs)
return int(rs[target_len])
r1 = 0
r2 = 0
for line in data.splitlines():
r1 += max_joltage(line, 2)
r2 += max_joltage(line, 12)
print(r1)
print(r2)

32
2025/d04.py Normal file
View File

@@ -0,0 +1,32 @@
from lib import get_data, Grid2D
data = get_data(__file__)
g = Grid2D(data)
r = 0
adjs = []
for pos in g.all_coords():
if g[pos] != "@":
continue
nr_of_rolls_adj = len([nb for nb in g.neighbors_adj(pos) if g[nb] == "@"])
if nr_of_rolls_adj < 4:
r += 1
adjs.append(pos)
print(r)
r = 0
while True:
adjs = []
for pos in g.all_coords():
if g[pos] != "@":
continue
nr_of_rolls_adj = len([nb for nb in g.neighbors_adj(pos) if g[nb] == "@"])
if nr_of_rolls_adj < 4:
adjs.append(pos)
if adjs:
r += len(adjs)
for a in adjs:
g[a] = "."
else:
break
print(r)

45
2025/d05.py Normal file
View File

@@ -0,0 +1,45 @@
from lib import get_data
data = get_data(__file__)
ranges, ids = data.split("\n\n")
ids = tuple(map(int, ids.splitlines()))
ranges = [list(map(int, line.split("-"))) for line in ranges.splitlines()]
updated = True
while updated:
updated = False
sorted_ranges = []
for lo, up in ranges:
assert lo <= up
for i in range(len(sorted_ranges)):
slo, sup = sorted_ranges[i]
if up + 1 < slo:
sorted_ranges.insert(i, (lo, up))
elif lo < slo:
sorted_ranges[i] = (lo, max(up, sup))
updated = True
elif lo <= sup:
sorted_ranges[i] = (slo, max(up, sup))
updated = True
else:
continue
break
else:
sorted_ranges.append((lo, up))
ranges = sorted_ranges
result_part_1 = 0
for id_to_check in ids:
for lo, up in ranges:
if lo <= id_to_check <= up:
result_part_1 += 1
break
print(result_part_1)
result_part_2 = 0
for lo, up in ranges:
result_part_2 += up - lo + 1
print(result_part_2)
assert result_part_2 == 350780324308385

60
2025/d06.py Normal file
View File

@@ -0,0 +1,60 @@
from lib import get_data
from typing import TypeVar
T = TypeVar('T')
data = """123 328 51 64
45 64 387 23
6 98 215 314
* + * + """
data = get_data(__file__)
def mul(xs):
r = 1
for x in xs:
r *= x
return r
lines = zip(*[line.split() for line in data.splitlines()])
r = 0
for xs in lines:
xs, op = xs[:-1], xs[-1]
xs = list(map(int, xs))
if op == "+":
r += sum(xs)
elif op == "*":
r += mul(xs)
else:
assert False, "Unexpected op"
print(r)
def split(xs: list[T], delim: T) -> list[list[T]]:
res = [[]]
for x in xs:
if x == delim:
res.append([])
else:
res[-1].append(x)
return res
chars_trans: list[tuple[str]] = list(zip(*[line for line in data.splitlines()]))
lines_trans: list[str] = list(map(lambda line: "".join(line).strip(), chars_trans))
cols: list[list[str]] = split(lines_trans, '')
r2 = 0
for xs in cols:
x0 = xs[0]
acc, op = int(x0[:-1]), x0[-1]
for x in xs[1:]:
x = int(x)
if op == "+":
acc += x
elif op == "*":
acc *= x
else:
assert False, "Unexpected op"
r2 += acc
print(r2)

59
2025/d07.py Normal file
View File

@@ -0,0 +1,59 @@
from lib import get_data, Grid2D
from collections import defaultdict
data = """.......S.......
...............
.......^.......
...............
......^.^......
...............
.....^.^.^.....
...............
....^.^...^....
...............
...^.^...^.^...
...............
..^...^.....^..
...............
.^.^.^.^.^...^.
..............."""
data = get_data(__file__)
g = Grid2D(data)
beams = [g.find('S')[0][1]]
splits = 0
for row in range(1, g.n_rows - 1):
new_beams = set()
for beam in beams:
field = g[(row, beam)]
if field == "^":
splits += 1
new_beams.add(beam - 1)
new_beams.add(beam + 1)
elif field == ".":
new_beams.add(beam)
else:
assert False, "unexpected field"
beams = list(new_beams)
# print(beams)
print(splits)
beams = {g.find('S')[0][1]: 1}
for row in range(1, g.n_rows - 1):
new_beams = defaultdict(int)
for beam, count in beams.items():
field = g[(row, beam)]
if field == "^":
new_beams[beam - 1] += count
new_beams[beam + 1] += count
elif field == ".":
new_beams[beam] += count
else:
assert False, "unexpected field"
beams = new_beams
print(sum(beams.values()))

View File

@@ -12,7 +12,21 @@ stressful and this will actually be more fun. Thank you Eric Wastl and let's go!
ticks naively. Maybe I should revisit this. ticks naively. Maybe I should revisit this.
- Day 2: The simple direct approach with iterating over all the IDs in the - Day 2: The simple direct approach with iterating over all the IDs in the
ranges just worked okay. Not pretty but acceptable. ranges just worked okay. Not pretty but acceptable.
- Day 3: - Day 3: Fun dynamic programming problem. Part 2 took me a little too long
overall but it was fun.
- Day 4: One of the easier grid based puzzles. Less than five minutes with
existing grid library.
- Day 5: A problem with ranges; I decided to implement proper range merging this
time because I always kind of avoid that. I could probably decrease the
complexity from O(n^2) to O(n log(n)) but I am happy that I've implemented
merging at all.
- Day 6: Transposing some rows and cols. Fun and good to keep the brain fit
but not really hard. I would have been way too slow for the leaderboard
in pre-AI years.
- Day 7: Grid puzzle that required non-naiv implementation for part 2. Took
me a second to realize that I could not save the coordinates by list but
had to use a count to be efficient.
- Day 8:
## AoC 2024 ## AoC 2024

10
pyproject.toml Normal file
View File

@@ -0,0 +1,10 @@
[project]
name = "aocpy"
version = "0.1.0"
description = "Make ruff and ty available via uv"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"ruff>=0.14.11",
"ty>=0.0.11",
]