advent-of-code-2025/day06.py
Tobias Radloff 8542b29e2e Day 6
2025-12-06 14:40:53 +01:00

102 lines
2.7 KiB
Python

#!/usr/bin/env python
# https://adventofcode.com/2025/day/5
import re, operator
from functools import reduce
f = open("day06input.txt", "r")
#f = open("testinput.txt", "r")
d = [l.strip("\n") for l in f.readlines()]
r = re.compile("\s+")
def get_op(s: str) -> callable:
if s == "*":
return operator.mul
elif s == "+":
return operator.add
else:
raise Exception("Unknown operator!")
def prep_data(raw_data: list[str]) -> list[str]:
# split lines
raw_data = [r.split(l) for l in raw_data]
# remove empty first/last element(s) if present (these occur when there are spaces before a data line's first or fater its final number/operator)
for d in raw_data:
if d[0] == "":
d.pop(0)
if d[-1] == "":
d.pop()
# make sure all data lines have the same length
assert all([len(raw_data[j+1]) - len(raw_data[j]) == 0 for j in range(len(raw_data) - 1)])
return raw_data
def part1(data: list[str]) -> int:
data = prep_data(data)
total = 0
# loop over number of elements per data line
for i in range(len(data[0])):
total += reduce(get_op(data[-1][i]), [int(data[j][i]) for j in range(len(data) - 1)])
return total
def part2(data: list[str]) -> int:
# get length of longest number in each column
# actually I'm counting the number of spaces between each operator but this value is equal to what we're looking for
num_lengths = [len(x) for x in r.findall(data[-1])]
# final num_length is too small b/c there's no single-space gap to the next element
num_lengths[-1] += 1
ops = prep_data([data[-1]])[0]
total = 0
r_left = re.compile("(^\s+)")
r_right = re.compile("(\s+$)")
for j in range(len(num_lengths)):
stripes = []
for i in range(len(data) - 1):
# cut out correct part of data line
d = data[i][:num_lengths[j]]
# replace spaces with dummy character at the start of the substring
m = r_left.search(d)
if m:
a, b = m.span()
d = "X" * (b - a) + d[b:]
# replace spaces with dummy character at the end of the substring
m = r_right.search(d)
if m:
a, b = m.span()
d = d[:a] + "X" * (b - a)
# store the prepped substring
stripes.append(d)
# clip substring from data line
data[i] = data[i][num_lengths[j]+1:]
# calculate the actual numbers
actual_nums = []
for i in range(len(stripes[0])):
num = "".join([stripes[k][i] for k in range(len(stripes))])
actual_nums.append(int(num.strip("X")))
# print(actual_nums)
# print(f"{j}\t{ops[j]}\t{get_op(ops[j])}\t{reduce(get_op(ops[j]), actual_nums)}")
total += reduce(get_op(ops[j]), actual_nums)
return total
print(part1(d))
print(part2(d))