My yearly advent-of-code solutions
1let filename = "./day_03_input.txt"
2let try_read ic = try Some (input_line ic) with End_of_file -> None
3
4let read_file ic =
5 let rec read acc =
6 match try_read ic with
7 | Some line -> read (line :: acc)
8 | None ->
9 close_in ic;
10 acc
11 in
12 read [] |> List.rev |> String.concat ""
13
14let regex = Str.regexp "mul(\\([0-9]+\\),\\([0-9]+\\))"
15let regex_mul_part_2 = Str.regexp "mul(\\([0-9]+\\),\\([0-9]+\\))\\|don't()"
16let regex_do_part_2 = Str.regexp "do()"
17
18let calculate_total str =
19 let rec calculate str acc =
20 try
21 let _ = Str.search_forward regex str 0 in
22 let a = Str.matched_group 1 str |> int_of_string in
23 let b = Str.matched_group 2 str |> int_of_string in
24
25 let result = a * b in
26 let new_str = Str.replace_first regex (string_of_int result) str in
27 calculate new_str (acc + result)
28 with Not_found -> acc
29 in
30 calculate str 0
31
32let calculate_total_part_2 str =
33 let rec calculate str regexp acc =
34 try
35 let _ = Str.search_forward regexp str 0 in
36 let cmd = Str.matched_group 0 str in
37 let new_str =
38 String.sub str (Str.match_end ()) (String.length str - Str.match_end ())
39 in
40 match cmd with
41 | "do()" -> calculate new_str regex_mul_part_2 acc
42 | "don't()" -> calculate new_str regex_do_part_2 acc
43 | cmd when String.starts_with ~prefix:"mul" cmd ->
44 let a = Str.matched_group 1 str |> int_of_string in
45 let b = Str.matched_group 2 str |> int_of_string in
46 let result = a * b in
47 calculate new_str regexp (acc + result)
48 | _ -> acc
49 with Not_found -> acc
50 in
51 calculate str regex_mul_part_2 0
52
53let () =
54 let ic = open_in filename in
55 read_file ic |> calculate_total |> Printf.sprintf "Sum %d" |> print_endline;
56
57 let ic = open_in filename in
58 read_file ic |> calculate_total_part_2
59 |> Printf.sprintf "Part 2 Sum %d"
60 |> print_endline