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()