let input = Reuse.split "inputs/day03.txt" '\n' let rec remove_last = function | [] -> [] | [_] -> [] | x :: xs -> x :: remove_last xs let get_highest_index (numbers : int list) : int = let rec loop entries current_index highest_index highest_value = match entries with | x :: xs -> if x > highest_value then loop xs (current_index + 1) current_index x else loop xs (current_index + 1) highest_index highest_value | [] -> highest_index in loop numbers 0 0 0 let joltage_for_line (line: string) : int = let char_list = line |> String.to_seq |> List.of_seq in let char_to_int c = Char.code c - Char.code '0' in let numbers = List.map char_to_int char_list in let index_highest_number = get_highest_index (remove_last numbers) in let index_highest_after = 1 + index_highest_number + get_highest_index (List.drop (index_highest_number + 1) numbers) in List.nth numbers index_highest_number * 10 + List.nth numbers index_highest_after let rec build_up_list (result: int list) (remaining: int list) : int list = let numbers_left = 12 - List.length result in let numbers_to_consider = List.take (List.length remaining - numbers_left + 1) remaining in let index_highest_number = get_highest_index (numbers_to_consider) in let highest_value = List.nth numbers_to_consider index_highest_number in let new_list = result @ [highest_value] in match List.length new_list with | 12 -> new_list | _ -> build_up_list new_list (List.drop (index_highest_number + 1) remaining) let rec int_pow x y = if y = 0 then 1 else x * int_pow x (y - 1) let joltage (line: string) : int = let char_list = line |> String.to_seq |> List.of_seq in let char_to_int c = Char.code c - Char.code '0' in let numbers = List.map char_to_int char_list in let result = build_up_list [] numbers in let rec loop to_process i acc = match to_process with | [] -> acc | x :: xs -> let power = int_pow 10 (i - 1) in loop xs (i - 1) (acc + (x * power)) in loop result (List.length result) 0 let solve_part1 (inputs: string list) : int = List.fold_left (fun acc entry -> acc + joltage_for_line entry) 0 inputs let solve_part2 (inputs: string list) : int = List.fold_left (fun acc entry -> acc + joltage entry) 0 inputs let day3_part1 : int = solve_part1 input let day3_part2 : int = solve_part2 input module Tests = struct let test_input = "987654321111111 811111111111119 234234234234278 818181911112111" let run_tests () = let test_lines = String.split_on_char '\n' test_input in let part1_result = solve_part1 test_lines in let part2_result = solve_part2 test_lines in if part1_result <> 357 then failwith ("Day 3 Part 1 test failed: expected 357, got " ^ string_of_int part1_result); if part2_result <> 3121910778619 then failwith ("Day 3 Part 2 test failed: expected 3121910778619, got " ^ string_of_int part2_result); Printf.printf "All day 3 tests passed!\n" end let () = Tests.run_tests()