From fa3468988e95beedf419ea19c9831fcf51254cdf Mon Sep 17 00:00:00 2001 From: John Costa Date: Tue, 3 Dec 2024 20:46:02 +0000 Subject: [PATCH] Day 3! --- .gitignore | 1 + AdventOfCode2024/AdventOfCode2024.opam | 1 + AdventOfCode2024/bin/main.ml | 2 +- AdventOfCode2024/dune-project | 2 +- AdventOfCode2024/lib/day_03.ml | 117 +++++++++++++++++++++++++ AdventOfCode2024/lib/dune | 3 +- 6 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 AdventOfCode2024/lib/day_03.ml diff --git a/.gitignore b/.gitignore index 038bfc4..3404485 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ ./zig-cache _build *.txt +dune.lock diff --git a/AdventOfCode2024/AdventOfCode2024.opam b/AdventOfCode2024/AdventOfCode2024.opam index b296c11..0eda58f 100644 --- a/AdventOfCode2024/AdventOfCode2024.opam +++ b/AdventOfCode2024/AdventOfCode2024.opam @@ -12,6 +12,7 @@ bug-reports: "https://github.com/username/reponame/issues" depends: [ "ocaml" "dune" {>= "3.16"} + "re2" "odoc" {with-doc} ] build: [ diff --git a/AdventOfCode2024/bin/main.ml b/AdventOfCode2024/bin/main.ml index d617642..06dbb1d 100644 --- a/AdventOfCode2024/bin/main.ml +++ b/AdventOfCode2024/bin/main.ml @@ -13,7 +13,7 @@ let read_lines name = let () = print_endline "\nAdvent of Code 2024"; let part1, part2 = - read_lines "./inputs/02.txt" |> AdventOfCode2024.Day_02.solve + read_lines "./inputs/03.txt" |> AdventOfCode2024.Day_03.solve in Printf.printf "Part 1: %s\nPart 2: %s\n" (string_of_int part1) (string_of_int part2) diff --git a/AdventOfCode2024/dune-project b/AdventOfCode2024/dune-project index 42dcf4f..f5d04df 100644 --- a/AdventOfCode2024/dune-project +++ b/AdventOfCode2024/dune-project @@ -19,7 +19,7 @@ (name AdventOfCode2024) (synopsis "A short synopsis") (description "A longer description") - (depends ocaml dune) + (depends ocaml dune re2) (tags (topics "to describe" your project))) diff --git a/AdventOfCode2024/lib/day_03.ml b/AdventOfCode2024/lib/day_03.ml new file mode 100644 index 0000000..4cd0b5e --- /dev/null +++ b/AdventOfCode2024/lib/day_03.ml @@ -0,0 +1,117 @@ +let rec print_list l = + match l with + | [] -> print_endline "" + | head :: tail -> + print_int head; + print_string " | "; + print_list tail + +let rec print_s_list l = + match l with + | [] -> print_endline "" + | head :: tail -> + print_string head; + print_string " | "; + print_s_list tail + +let rec print_tuple_list l = + match l with + | [] -> print_endline "" + | (index, value) :: tail -> + print_int index; + print_string ", "; + print_string (string_of_bool value); + print_string " | "; + print_tuple_list tail + +let get_toggle_positions line = + let toggle_on_regex = Re2.create_exn {|do\(\)|} in + let toggle_off_regex = Re2.create_exn {|don't\(\)|} in + let on_matches = Re2.get_matches_exn toggle_on_regex line in + let off_matches = Re2.get_matches_exn toggle_off_regex line in + let get_indexes = + List.fold_left + (fun acc i -> + let start, _ = Re2.Match.get_pos_exn ~sub:(`Index 0) i in + [ start ] @ acc) + [] + in + + let on_indexes = get_indexes on_matches in + let off_indexes = get_indexes off_matches in + List.sort + (fun (i, _) (j, _) -> i - j) + ((List.rev on_indexes |> List.map (fun i -> (i, true))) + @ (List.rev off_indexes |> List.map (fun i -> (i, false)))) + +let get_all_numbers_positions line = + let instruction_regex = Re2.create_exn {|mul\((\d+),(\d+)\)|} in + let matches_indexes = Re2.get_matches_exn instruction_regex line in + let indexes = + List.fold_left + (fun acc i -> + let start, _ = Re2.Match.get_pos_exn ~sub:(`Index 0) i in + [ start ] @ acc) + [] matches_indexes + in + List.rev indexes + +let get_all_numbers line = + let instruction_regex = Re2.create_exn {|mul\((\d+),(\d+)\)|} in + let matches = Re2.find_all_exn instruction_regex line in + let nums = + List.fold_left + (fun acc m -> + let num1, num2 = Scanf.sscanf m "mul(%d,%d)" (fun n1 n2 -> (n1, n2)) in + [ (num1, num2) ] @ acc) + [] matches + in + List.rev nums + +let get_closest_item l item starting = + let rec get_closest_item' l closest item = + match l with + | [] -> closest + | (head, v) :: tail -> + if head < item then get_closest_item' tail (head, v) item else closest + in + get_closest_item' l (0, starting) item + +let solve lines = + let part1 = + List.fold_left + (fun acc line -> + let line_value = + List.fold_left + (fun acc (num1, num2) -> acc + (num1 * num2)) + 0 (get_all_numbers line) + in + acc + line_value) + 0 lines + in + + let part2, _ = + List.fold_left + (fun (acc, toggle) line -> + let mul_indexes = get_all_numbers_positions line in + let mul_intructions = get_all_numbers line in + let toggles = get_toggle_positions line in + let closest_check = get_closest_item toggles in + + let rec loop indexes instructions acc last_toggle = + match (indexes, instructions) with + | [], [] -> (acc, last_toggle) + | head :: tail, (n1, n2) :: in_tail -> + let _, is_on = closest_check head toggle in + + let acc' = if is_on then acc + (n1 * n2) else acc in + loop tail in_tail acc' is_on + | _ -> (acc, last_toggle) + in + + let acc', last_toggle = loop mul_indexes mul_intructions 0 toggle in + (acc + acc', last_toggle)) + (0, true) lines + in + + (part1, part2) diff --git a/AdventOfCode2024/lib/dune b/AdventOfCode2024/lib/dune index 306de01..b0f4847 100644 --- a/AdventOfCode2024/lib/dune +++ b/AdventOfCode2024/lib/dune @@ -1,2 +1,3 @@ (library - (name AdventOfCode2024)) + (name AdventOfCode2024) + (libraries re2))