Code improvement day1, solved day2
This commit is contained in:
@ -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
|
||||
|
||||
1
inputs/day02.txt
Normal file
1
inputs/day02.txt
Normal file
@ -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
|
||||
@ -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()
|
||||
|
||||
@ -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 ()
|
||||
80
lib/day2.ml
Normal file
80
lib/day2.ml
Normal file
@ -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()
|
||||
@ -5,5 +5,5 @@ let read filename =
|
||||
close_in ic;
|
||||
content
|
||||
|
||||
let split_lines filename =
|
||||
String.split_on_char '\n' (read filename)
|
||||
let split filename char =
|
||||
String.split_on_char char (read filename)
|
||||
Reference in New Issue
Block a user