fun numberAt (i : int) = fn (s : string) => if i >= String.size s then NONE else SOME (Substring.takel Char.isDigit (Substring.extract (s, i, NONE))) fun substrToInt (n : substring) = valOf (Int.fromString (Substring.string n)) fun sum (l : int list) : int = foldl (op +) 0 l val file = TextIO.openIn "day_3.txt" val input = TextIO.inputAll file; TextIO.closeIn file; val instructions = List.tabulate ((size input), (fn i => let val n1 = numberAt (i + 4) input val n2 = Option.mapPartial (fn n => numberAt (i + 5 + Substring.size n) input) n1 in if isSome n1 andalso isSome n2 andalso String.substring (input, i, 4) = "mul(" andalso String.sub (input, i + 4 + Substring.size (valOf n1)) = #"," andalso String.sub (input, i + 5 + Substring.size (valOf n1) + Substring.size (valOf n2)) = #")" then SOME (n1, n2) else NONE end)) val instructions = List.mapPartial (fn (num) => case num of SOME (SOME x, SOME y) => SOME (substrToInt x, substrToInt y) | _ => NONE) instructions val result = sum (map (op *) instructions)