95 lines
3.2 KiB
OCaml
95 lines
3.2 KiB
OCaml
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 = "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 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() |