50 lines
1.4 KiB
OCaml
50 lines
1.4 KiB
OCaml
(** Type containing commands available in input *)
|
|
type cmd =
|
|
| Do (** Enable processing *)
|
|
| Donot (** Disable processing *)
|
|
| Mul of int * int (** Multiply two integers. *)
|
|
|
|
(** [find_nums s] returns the list of instructions given in [s]. *)
|
|
let cmds_of_string s =
|
|
let r =
|
|
Str.regexp
|
|
{|do()\|don't()\|mul(\([0-9][0-9]?[0-9]?\),\([0-9][0-9]?[0-9]?\))|}
|
|
in
|
|
let rec impl acc pos =
|
|
try
|
|
let _ = Str.search_forward r s pos in
|
|
let action =
|
|
match Str.matched_group 0 s with
|
|
| "do()" -> Do
|
|
| "don't()" -> Donot
|
|
| _ ->
|
|
Mul
|
|
( int_of_string (Str.matched_group 1 s),
|
|
int_of_string (Str.matched_group 2 s) )
|
|
in
|
|
impl (action :: acc) (Str.match_end ())
|
|
with Not_found -> acc
|
|
in
|
|
List.rev (impl [] 0)
|
|
|
|
let cmds_of_file fname =
|
|
Aoc.strings_of_file fname |> List.map cmds_of_string |> List.concat
|
|
|
|
(** [mac acc a b] returns [acc + a * b]. *)
|
|
let mac acc = function Mul (a, b) -> acc + (a * b) | _ -> acc
|
|
|
|
let day2403a = List.fold_left mac 0
|
|
|
|
let day2403b lst =
|
|
let rec impl acc enabled = function
|
|
| [] -> acc
|
|
| Do :: t -> impl acc true t
|
|
| Donot :: t -> impl acc false t
|
|
| Mul (a, b) :: t ->
|
|
if enabled then impl (acc + (a * b)) true t else impl acc false t
|
|
in
|
|
impl 0 true lst
|
|
|
|
let _ =
|
|
Aoc.main cmds_of_file [ (string_of_int, day2403a); (string_of_int, day2403b) ]
|