Nim
The hardest part was reading the part 2 description. I literally looked at it for minutes trying to understand where the problem numbers come from and how they're related to the example input. But then it clicked.
The next roadblock was that my template was stripping whitespace at the end of the last line, making parsing a lot harder. I've replaced strip() with strip(chars={'\n'}) to keep the trailing space intact.
Runtime: 1.4 ms 618 ฮผs
view code
type
AOCSolution[T,U] = tuple[part1: T, part2: U]
proc solve(input: string): AOCSolution[int, int] =
let lines = input.splitLines()
let numbers = lines[0..^2]
let ops = lines[^1]
block p1:
let numbers = numbers.mapIt(it.splitWhiteSpace().mapIt(parseInt it))
let ops = ops.splitWhitespace()
for x in 0 .. numbers[0].high:
var res = numbers[0][x]
for y in 1 .. numbers.high:
case ops[x]
of "*": res *= numbers[y][x]
of "+": res += numbers[y][x]
result.part1 += res
block p2:
var problems: seq[(char, Slice[int])]
var ind = 0
while ind < ops.len:
let len = ops.skipWhile({' '}, ind+1)
problems.add (ops[ind], ind .. ind + len - (if ind+len < ops.high: 1 else: 0))
ind += len + 1
for (op, cols) in problems:
var res = 0
for x in cols:
var num = ""
for y in 0 .. numbers.high:
num &= numbers[y][x]
if res == 0:
res = parseInt num.strip
else:
case op
of '*': res *= parseInt num.strip
of '+': res += parseInt num.strip
else: discard
result.part2 += res
Full solution at Codeberg: solution.nim