···
+
input = builtins.readFile ../../shared/06/input.txt;
+
lines = builtins.filter (s: builtins.isString s && s != "") (builtins.split "\n" input);
+
# Helper to get character at position or space if out of bounds
+
if idx < 0 || idx >= builtins.stringLength str
+
else builtins.substring idx 1 str;
+
# Find whitespace columns (columns that are all spaces/tabs in data rows)
+
dataRows = builtins.genList (i: builtins.elemAt lines i) (builtins.length lines - 1);
+
maxLen = builtins.foldl' (max: row:
+
let len = builtins.stringLength row;
+
in if len > max then len else max
+
# Find columns that are all whitespace
+
splitCols = builtins.filter (col: col != null) (builtins.genList (i:
+
allWS = builtins.foldl' (acc: row:
+
acc && (let ch = charAt row i; in ch == " " || ch == " ")
+
in if allWS then i else null
+
# Split each row at whitespace columns
+
rowLen = builtins.stringLength row;
+
splitImpl = cuts: startPos: acc:
+
if builtins.length cuts == 0
+
then acc ++ [(builtins.substring startPos (rowLen - startPos) row)]
+
cut = builtins.head cuts;
+
restCuts = builtins.tail cuts;
+
end = if cut + 1 > rowLen then rowLen else cut + 1;
+
segment = builtins.substring startPos (end - startPos) row;
+
in splitImpl restCuts end (acc ++ [segment]);
+
in splitImpl splitCols 0 [];
+
# Split all lines (including operator row)
+
segmentedRows = builtins.map splitRow lines;
+
# Transpose to get columns (problems)
+
numProblems = builtins.length (builtins.head segmentedRows);
+
problems = builtins.genList (colIdx:
+
builtins.map (row: builtins.elemAt row colIdx) segmentedRows
+
# Fast trim - just remove spaces and tabs
+
# Extract just digits from a string for numbers
+
cleaned = builtins.replaceStrings [" " " "] ["" ""] str;
+
in if builtins.stringLength cleaned == 0 then 0 else builtins.fromJSON cleaned;
+
cleaned = builtins.replaceStrings [" " " "] ["" ""] str;
+
# Part 1: Normal left-to-right evaluation
+
part1 = builtins.foldl' (total: problem:
+
lastIdx = builtins.length problem - 1;
+
operator = extractOp (builtins.elemAt problem lastIdx);
+
nums = builtins.map (s: extractNum s) (builtins.genList (i: builtins.elemAt problem i) lastIdx);
+
then builtins.foldl' (acc: n: acc * n) 1 nums
+
else builtins.foldl' (acc: n: acc + n) 0 nums;
+
# Part 2: Cepheid (vertical) reading
+
part2 = builtins.foldl' (total: problem:
+
lastIdx = builtins.length problem - 1;
+
operator = extractOp (builtins.elemAt problem lastIdx);
+
numStrs = builtins.genList (i: builtins.elemAt problem i) lastIdx;
+
maxWidth = builtins.foldl' (max: s:
+
let len = builtins.stringLength s;
+
in if len > max then len else max
+
# Read vertically from right to left
+
cephNums = builtins.filter (n: n != null) (builtins.genList (colR:
+
# Build digits string from this column (right to left)
+
digitsStr = builtins.concatStringsSep "" (builtins.filter (ch: ch != " " && ch != " ") (builtins.map (s:
+
if idx >= 0 && idx < builtins.stringLength s
+
then builtins.substring idx 1 s
+
in if builtins.stringLength digitsStr > 0
+
then builtins.fromJSON digitsStr
+
then builtins.foldl' (acc: n: acc * n) 1 cephNums
+
else builtins.foldl' (acc: n: acc + n) 0 cephNums;