82 lines
2.2 KiB
Python
82 lines
2.2 KiB
Python
#!/usr/bin/env python
|
|
|
|
# https://adventofcode.com/2025/day/6
|
|
|
|
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
|
|
|
|
for j in range(len(num_lengths)):
|
|
stripes = []
|
|
for i in range(len(data) - 1):
|
|
# cut out correct part of data line
|
|
stripes.append(data[i][:num_lengths[j]])
|
|
# 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()))
|
|
# 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))
|
|
|
|
|