From 747e649db45817a23aaf7cb498018a09c7d984e5 Mon Sep 17 00:00:00 2001 From: Klotz Date: Wed, 3 Dec 2025 10:38:04 +0100 Subject: [PATCH] Code improvement day1, solved day2 --- bin/main.ml | 5 +- inputs/{day1.txt => day01.txt} | 0 inputs/day02.txt | 1 + lib/day1.ml | 8 +-- lib/day1_improved.ml | 102 --------------------------------- lib/day2.ml | 80 ++++++++++++++++++++++++++ lib/reuse.ml | 4 +- 7 files changed, 90 insertions(+), 110 deletions(-) rename inputs/{day1.txt => day01.txt} (100%) create mode 100644 inputs/day02.txt delete mode 100644 lib/day1_improved.ml create mode 100644 lib/day2.ml diff --git a/bin/main.ml b/bin/main.ml index 74967d3..3ee6bed 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -1,2 +1,3 @@ -let () = Printf.printf "%i\n" Aoc25.Day1.day1_part1 -let () = Printf.printf "%i\n" Aoc25.Day1.day1_part2 +let () = Printf.printf "Solution Day 1 part 1: %i\n" Aoc25.Day1.day1_part1 +let () = Printf.printf "Solution Day 1 part 2: %i\n" Aoc25.Day1.day1_part2 +let () = Printf.printf "Solution Day 2 part 1: %i\n" Aoc25.Day2.day2_part1 diff --git a/inputs/day1.txt b/inputs/day01.txt similarity index 100% rename from inputs/day1.txt rename to inputs/day01.txt diff --git a/inputs/day02.txt b/inputs/day02.txt new file mode 100644 index 0000000..31ccd39 --- /dev/null +++ b/inputs/day02.txt @@ -0,0 +1 @@ +1061119-1154492,3-23,5180469-5306947,21571-38630,1054-2693,141-277,2818561476-2818661701,21177468-21246892,40-114,782642-950030,376322779-376410708,9936250-10074071,761705028-761825622,77648376-77727819,2954-10213,49589608-49781516,9797966713-9797988709,4353854-4515174,3794829-3861584,7709002-7854055,7877419320-7877566799,953065-1022091,104188-122245,25-39,125490-144195,931903328-931946237,341512-578341,262197-334859,39518-96428,653264-676258,304-842,167882-252124,11748-19561 \ No newline at end of file diff --git a/lib/day1.ml b/lib/day1.ml index 84076c8..35e2bb5 100644 --- a/lib/day1.ml +++ b/lib/day1.ml @@ -1,5 +1,5 @@ -let input = Reuse.split_lines "inputs/day1.txt" +let input = Reuse.split "inputs/day01.txt" '\n' let convert (s : string): int = @@ -73,12 +73,12 @@ let run_tests () = let part1_result = solve_part1 test_lines in let part2_result = solve_part2 test_lines in if part1_result <> 3 then - failwith ("Part 1 test failed: expected 3, got " ^ string_of_int part1_result); + failwith ("Day 1 Part 1 test failed: expected 3, got " ^ string_of_int part1_result); if part2_result <> 8 then - failwith ("Part 2 test failed: expected 8, got " ^ string_of_int part2_result); + failwith ("Day 1 Part 2 test failed: expected 8, got " ^ string_of_int part2_result); - Printf.printf "All tests passed!\n" + Printf.printf "All Day 1 tests passed!\n" end let () = Tests.run_tests() diff --git a/lib/day1_improved.ml b/lib/day1_improved.ml deleted file mode 100644 index 345726d..0000000 --- a/lib/day1_improved.ml +++ /dev/null @@ -1,102 +0,0 @@ -(* Improved version of day1.ml with better code quality *) - -let input = Reuse.split_lines "inputs/day1.txt" - -(* Improved: Better function name and documentation *) -let parse_direction (s : string) : int = - if String.length s = 0 then - invalid_arg "Empty direction string" - else - let direction = s.[0] in - let distance_str = String.sub s 1 (String.length s - 1) in - let distance = int_of_string distance_str in - match direction with - | 'L' -> -distance (* Negative for left turns *) - | 'R' -> distance (* Positive for right turns *) - | _ -> invalid_arg ("Invalid direction: " ^ String.make 1 direction) - -(* Improved: More descriptive function name *) -let count_if_at_origin (counter : int) (position : int) : int = - if position = 0 then counter + 1 else counter - -(* Improved: Better function name and clearer logic *) -let normalize_position (position : int) (modulus : int) : int = - let result = position mod modulus in - if result >= 0 then result else result + modulus - -(* Improved: More descriptive function name and clearer logic *) -let count_boundary_crossings (counter : int) (old_position : int) (movement : int) : int = - Printf.printf "Position %i, movement %i, current counter %i\n" old_position movement counter; - - (* Count full rotations (every 100 units) *) - let full_rotations = abs movement / 100 in - let remaining_movement = movement mod 100 in - let new_position = old_position + remaining_movement in - - (* Count boundary crossings *) - let boundary_crossings = - if (new_position >= 100 && old_position < 100) || - (new_position <= 0 && old_position > 0) then 1 else 0 - in - - counter + full_rotations + boundary_crossings - -(* Improved: More descriptive function names *) -let rec solve_with_origin_counting (movements : int list) (position : int) (counter : int) : int = - match movements with - | [] -> counter - | movement :: remaining -> - let new_position = normalize_position (position + movement) 100 in - solve_with_origin_counting remaining new_position (count_if_at_origin counter new_position) - -let rec solve_with_boundary_counting (movements : int list) (position : int) (counter : int) : int = - match movements with - | [] -> counter - | movement :: remaining -> - let new_position = normalize_position (position + movement) 100 in - let new_counter = count_boundary_crossings counter position movement in - solve_with_boundary_counting remaining new_position new_counter - -(* Improved: Clear, descriptive function names *) -let solve_part1 (lines : string list) : int = - let movements = List.map parse_direction lines in - solve_with_origin_counting movements 50 0 - -let solve_part2 (lines : string list) : int = - let movements = List.map parse_direction lines in - solve_with_boundary_counting movements 50 0 - -(* Main solutions *) -let day1_part1 : int = solve_part1 input -let day1_part2 : int = solve_part2 input - -(* Improved: Better test organization *) -module Tests = struct - let test_input = "L268 -L30 -R48 -L5 -R60 -L55 -L1 -L99 -R14 -L82" - - let test_lines = String.split_on_char '\n' test_input - - let run_tests () = - let part1_result = solve_part1 test_lines in - let part2_result = solve_part2 test_lines in - - if part1_result <> 3 then - failwith ("Part 1 test failed: expected 3, got " ^ string_of_int part1_result); - - if part2_result <> 8 then - failwith ("Part 2 test failed: expected 8, got " ^ string_of_int part2_result); - - Printf.printf "All tests passed!\n" -end - -(* Run tests *) -let () = Tests.run_tests () diff --git a/lib/day2.ml b/lib/day2.ml new file mode 100644 index 0000000..f357b0e --- /dev/null +++ b/lib/day2.ml @@ -0,0 +1,80 @@ +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 calculate_for_line ((start, ending) : (string * string)) : 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 is_invalid i then i else 0) + in + loop start_number 0 + + +let rec calculate_invalidities (entries: (string * string) list) (result : int): int = + match entries with + | x :: xs -> calculate_invalidities xs (result + calculate_for_line x) + | _ -> result + + + +let solve_part1 (inputs: string list) : int = + let inputs = generate_pairs inputs in + let filtered = List.filter is_valid inputs in + let result = 0 in + calculate_invalidities filtered result + + + +let solve_part2 (inputs: string list) : int = + List.length inputs + +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() diff --git a/lib/reuse.ml b/lib/reuse.ml index a40e226..8c9b355 100644 --- a/lib/reuse.ml +++ b/lib/reuse.ml @@ -5,5 +5,5 @@ let read filename = close_in ic; content -let split_lines filename = - String.split_on_char '\n' (read filename) \ No newline at end of file +let split filename char = + String.split_on_char char (read filename) \ No newline at end of file