82 lines
2.8 KiB
OCaml
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 0, got " ^ string_of_int part2_result);
|
|
|
|
Printf.printf "All day 2 tests passed!\n"
|
|
end
|
|
|
|
let () = Tests.run_tests()
|