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