advent of code 2025 in ts and nix
at main 3.2 kB view raw
1let 2 input = builtins.readFile ../../shared/03/input.txt; 3 banks = builtins.filter (s: builtins.isString s && s != "") (builtins.split "\n" input); 4 5 # Helper to convert string to list of digit ints 6 stringToDigits = str: 7 let 8 len = builtins.stringLength str; 9 indices = builtins.genList (i: i) len; 10 in map (i: builtins.fromJSON (builtins.substring i 1 str)) indices; 11 12 # Part 1: Find highest pair (largestI * 10 + jVal) for each bank 13 part1 = 14 let 15 processBank = bank: 16 let 17 digits = stringToDigits bank; 18 L = builtins.length digits; 19 20 # For each position j, find the largest digit before it and form pair 21 processPair = state: j: 22 let 23 jVal = builtins.elemAt digits j; 24 # Find largest digit in digits[0..j-1] 25 largestI = builtins.foldl' 26 (max: i: let iVal = builtins.elemAt digits i; in if iVal > max then iVal else max) 27 (-1) 28 (builtins.genList (i: i) j); 29 pair = largestI * 10 + jVal; 30 newHighest = if pair > state.highest then pair else state.highest; 31 in { highest = newHighest; }; 32 33 # Process j from 1 to L-1 34 result = builtins.foldl' 35 processPair 36 { highest = -1; } 37 (builtins.genList (i: i + 1) (L - 1)); 38 in result.highest; 39 40 jolts = map processBank banks; 41 in builtins.foldl' builtins.add 0 jolts; 42 43 # Part 2: Monotonic stack to find best K-digit number 44 part2 = 45 let 46 K = 12; 47 48 processBank = bank: 49 let 50 digits = stringToDigits bank; 51 L = builtins.length digits; 52 53 # Process each digit with monotonic stack approach 54 processDigit = state: j: 55 let 56 jVal = builtins.elemAt digits j; 57 remaining = L - j; 58 59 # Pop smaller tail digits if we can still reach K 60 popSmaller = stack: 61 let 62 stackLen = builtins.length stack; 63 canPop = stackLen > 0 && 64 (builtins.elemAt stack (stackLen - 1)) < jVal && 65 stackLen - 1 + remaining >= K; 66 in 67 if canPop then 68 popSmaller (builtins.genList (i: builtins.elemAt stack i) (stackLen - 1)) 69 else 70 stack; 71 72 newStack = popSmaller state.stack; 73 stackLen = builtins.length newStack; 74 75 # Add current digit if we still need more 76 finalStack = if stackLen < K then newStack ++ [jVal] else newStack; 77 in { stack = finalStack; }; 78 79 # Process all digits 80 result = builtins.foldl' 81 processDigit 82 { stack = []; } 83 (builtins.genList (i: i) L); 84 85 # Convert stack to number 86 stackToNum = builtins.foldl' (acc: d: acc * 10 + d) 0 result.stack; 87 in stackToNum; 88 89 jolts = map processBank banks; 90 in builtins.foldl' builtins.add 0 jolts; 91 92in { 93 inherit part1 part2; 94}