95 lines
2.7 KiB
OCaml
95 lines
2.7 KiB
OCaml
let compare_ranges fr sr = if fst fr > fst sr then 1 else -1
|
|
let split_empty_line lines =
|
|
let rec split acc = function
|
|
| [] -> (List.rev acc), []
|
|
| "" :: xs -> (List.rev acc), xs
|
|
| x :: xs -> split (x::acc) xs
|
|
in
|
|
split [] lines
|
|
|
|
let input = Reuse.split "inputs/day05.txt" '\n'
|
|
|
|
let create_ingredients lines =
|
|
List.map (fun x -> int_of_string x) lines
|
|
let create_ranges lines =
|
|
let splits = List.map (fun line -> String.split_on_char '-' line) lines in
|
|
List.map (fun line -> (int_of_string (List.nth line 0) , int_of_string (List.nth line 1))) splits
|
|
|
|
let is_fresh number ranges =
|
|
let valid_ranges = List.filter (fun (x,y) -> number >= x && number <= y) ranges in
|
|
if List.length valid_ranges > 0 then 1 else 0
|
|
|
|
|
|
let solve_part1 inputs =
|
|
let (first, second) = split_empty_line inputs in
|
|
let second = List.filter (fun x -> x <> "") second in
|
|
let ingredients = create_ingredients second in
|
|
let ranges = create_ranges first in
|
|
List.fold_left (fun acc entry -> acc + (is_fresh entry ranges)) 0 ingredients
|
|
|
|
let update_range (x, y) ranges =
|
|
List.fold_left (fun (u1, u2) (t1, t2) ->
|
|
Printf.printf "Updating range step (%i, %i) with (%i, %i)\n" u1 u2 t1 t2;
|
|
if t1 = u1 && t2 = u2 then (u1, u2)
|
|
else if u1 > t2 then (u1, u2)
|
|
else if u2 < t1 then (u1, u2)
|
|
else if t1 <= u1 && t2 >= u2 then (0,0)
|
|
else if t1 >= u1 && u2 <= t2 then (u1, t1 - 1)
|
|
else if t1 <= u1 && u2 >= t2 then (t2 + 1, u2)
|
|
else (u1 ,u2)
|
|
) (x, y) ranges
|
|
|
|
let rec update_ranges to_process updated_ranges =
|
|
match to_process with
|
|
| [] -> updated_ranges
|
|
| (x, y) :: xs ->
|
|
let (u1, u2) = update_range (x, y) xs in
|
|
let removed = List.filter (fun (t1, t2) -> not (t1 <= u2 && t2 >= u1 && u2 <= t2)) xs in
|
|
update_ranges removed ((u1, u2) :: updated_ranges)
|
|
|
|
let solve_part2 inputs =
|
|
let (first, _) = split_empty_line inputs in
|
|
let ranges = create_ranges first in
|
|
let updated = update_ranges ranges [] in
|
|
let updated = List.filter (fun (x,y) -> x + y <> 0) updated in
|
|
List.fold_left (fun acc (x, y) -> acc + (y - x) + 1) 0 updated
|
|
|
|
|
|
|
|
let day5_part1 : int =
|
|
solve_part1 input
|
|
|
|
let day5_part2 : int =
|
|
solve_part2 input
|
|
|
|
module Tests = struct
|
|
let test_input = "3-5
|
|
10-14
|
|
16-20
|
|
12-18
|
|
|
|
1
|
|
5
|
|
8
|
|
11
|
|
17
|
|
32"
|
|
|
|
|
|
|
|
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 <> 3 then
|
|
failwith ("Day 5 Part 1 test failed: expected 3, got " ^ string_of_int part1_result);
|
|
|
|
if part2_result <> 14 then
|
|
failwith ("Day 4 Part 2 test failed: expected 14, got " ^ string_of_int part2_result);
|
|
|
|
Printf.printf "All day 4 tests passed!\n"
|
|
end
|
|
|
|
let () = Tests.run_tests()
|