{ lib, utils, ... }: with lib; with builtins; with utils; let records = map (l: let s = reSplit ": " l; in { target = toInt (head s); candidates = map toInt (splitWhitespace (last s)); }) (readLines ./input); concatInts = x: y: toIntBase10 "${toString x}${toString y}"; canProduce' = current: target: candidates: ops: if current > target then false else if candidates == [ ] then current == target else any (op: canProduce' (op current (head candidates)) target (tail candidates) ops) ops; canProduce = operators: r: if r.candidates == [ ] then r.target == 0 else canProduce' (head r.candidates) r.target (tail r.candidates) operators; in { part1 = listSumWith (getAttr "target") (filter (canProduce [ add mul ]) records); part2 = listSumWith (getAttr "target") (filter (canProduce [ add mul concatInts ]) records); }