adventofcode-2024/day_3.sml

64 lines
2.0 KiB
Standard ML
Raw Permalink Normal View History

2024-12-07 16:50:31 +00:00
datatype instruction = NOOP | DO | DONT | MUL of (int * int)
2024-12-05 17:03:34 +00:00
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)))
2024-12-07 16:50:31 +00:00
fun startsWith (needle : string, haystack : string, pos : int) =
size haystack > pos + size needle andalso String.substring (haystack, pos, size needle) = needle
2024-12-05 17:03:34 +00:00
2024-12-07 16:50:31 +00:00
fun substrToInt (n : substring) = valOf (Int.fromString (Substring.string n))
2024-12-05 17:03:34 +00:00
val file = TextIO.openIn "day_3.txt"
val input = TextIO.inputAll file;
TextIO.closeIn file;
val instructions = List.tabulate ((size input), (fn i =>
2024-12-07 16:50:31 +00:00
if startsWith ("do()", input, i) then DO
else if startsWith ("don't()", input, i) then DONT
else
let
val n1 = numberAt (i + 4) input
val n2 = Option.mapPartial (fn n => numberAt (i + 5 + Substring.size n) input) n1
in
case (n1, n2) of
(SOME(a), SOME(b)) =>
if
startsWith ("mul(", input, i) andalso
String.sub (input, i + 4 + Substring.size a) = #"," andalso
String.sub (input, i + 5 + Substring.size a + Substring.size b) = #")"
then MUL (substrToInt a, substrToInt b) else NOOP
| _ => NOOP
end
))
val instructions = List.filter (fn (ins) => ins <> NOOP) instructions
fun calculate (instructions : instruction vector) =
Vector.foldl (fn (ins, v) => case ins of MUL (a, b) => v + a * b | _ => v) 0 instructions
(* Part 1 *)
val mulOnlyResult = calculate (Vector.fromList instructions)
(* Part 2 *)
val filteredInstructions = Vector.mapi
(fn (i, ins) =>
let
val prevInstructions = List.rev (List.take (instructions, i))
val lastToggle = List.find (fn (ins) => ins = DO orelse ins = DONT) prevInstructions
val shouldMultiply = case lastToggle of
SOME (ins) => ins = DO
| NONE => true
in
case ins of
MUL (a, b) => if shouldMultiply then ins else NOOP
| _ => ins
end
)
(Vector.fromList instructions)
val allInsResult = calculate filteredInstructions
2024-12-05 17:03:34 +00:00