aoc25_ocaml/lib/day2.ml
2025-12-05 00:01:25 +01:00

82 lines
2.8 KiB
OCaml

let input = Reuse.split "inputs/day02.txt" ','
let is_valid ((start, ending): string * string) : bool =
let start_length = String.length start in
let end_length = String.length ending in
let filtered_out = start_length mod 2 != 0 && end_length mod 2 != 0 && start_length == end_length in
not filtered_out
let generate_tuple (value : string) : (string * string) =
let split = String.split_on_char '-' value in
match split with
| first :: second :: [] -> (first, second)
| _ -> failwith("Expected exactly 2 values in list entry" ^ value)
let generate_pairs (inputs: string list) : (string * string ) list =
List.map generate_tuple inputs
let is_invalid (number: int) : bool =
let number_string = string_of_int number in
let length = String.length number_string in
let is_even = length mod 2 == 0 in
let half = length / 2 in
let first_part = String.sub number_string 0 half in
let last_part = String.sub number_string half half in
let invalid = is_even && first_part = last_part in
invalid
let is_invalid_2 (number: int) : bool =
let number_string = string_of_int number in
let pattern = Str.regexp "\\(.+\\)\\1+$" in
Str.string_match pattern number_string 0
let calculate_for_line ((start, ending) : (string * string)) (inv: int -> bool) : int =
let start_number = int_of_string start in
let end_number = int_of_string ending in
let rec loop i acc =
if i > end_number then acc
else loop (i + 1) (acc + if inv i then i else 0)
in
loop start_number 0
let calculate_invalidities entries inv =
List.fold_left (fun acc entry -> acc + calculate_for_line entry inv) 0 entries
let solve_part1 (inputs: string list) : int =
let inputs = generate_pairs inputs in
let filtered = List.filter is_valid inputs in
calculate_invalidities filtered is_invalid
let solve_part2 (inputs: string list) : int =
let inputs = generate_pairs inputs in
calculate_invalidities inputs is_invalid_2
let day2_part1 : int =
solve_part1 input
let day2_part2 : int =
solve_part2 input
module Tests = struct
let test_input = "11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124"
let test_lines = String.split_on_char ',' test_input
let run_tests () =
let part1_result = solve_part1 test_lines in
let part2_result = solve_part2 test_lines in
if part1_result <> 1227775554 then
failwith ("Day 2 Part 1 test failed: expected 1227775554, got " ^ string_of_int part1_result);
if part2_result <> 4174379265 then
failwith ("Day 2 Part 2 test failed: expected 4174379265, got " ^ string_of_int part2_result);
Printf.printf "All day 2 tests passed!\n"
end
let () = Tests.run_tests()