This commit is contained in:
2024-12-06 20:47:18 +00:00
parent 233dda4fe9
commit cbcb0c567c
2 changed files with 134 additions and 1 deletions

View File

@ -13,7 +13,7 @@ let read_lines name =
let () =
print_endline "\nAdvent of Code 2024";
let part1, part2 =
read_lines "./inputs/05.txt" |> AdventOfCode2024.Day_05.solve
read_lines "./inputs/06.txt" |> AdventOfCode2024.Day_06.solve
in
Printf.printf "Part 1: %s\nPart 2: %s\n" (string_of_int part1)
(string_of_int part2)

View File

@ -0,0 +1,133 @@
module IntTuple = struct
type t = int * int * int * int
let compare (x0, y0, z0, w0) (x1, y1, z1, w1) =
if x0 == x1 && y0 == y1 && z0 == z1 && w0 == w1 then 0 else 1
end
module IntTupleSet = Set.Make (IntTuple)
let find_position lines =
let rec loop list_index lines =
match lines with
| [] -> raise (Invalid_argument "not found")
| head :: tail -> (
match String.index_from_opt head 0 '^' with
| None -> loop (list_index + 1) tail
| Some i -> (list_index, i))
in
loop 0 lines
let remove_list_duplicates l =
let rec loop acc l =
match l with
| [] -> acc
| (y1, x1) :: tail ->
if List.exists (fun (y2, x2) -> x1 == x2 && y1 == y2) acc then
loop acc tail
else loop ([ (y1, x1) ] @ acc) tail
in
loop [] l
let get_direction_change direction =
match direction with
| -1, 0 -> (0, 1)
| 1, 0 -> (0, -1)
| 0, 1 -> (1, 0)
| 0, -1 -> (-1, 0)
| _ -> raise (Invalid_argument "not valid direction")
let is_out_of_bounds l (y, x) =
y < 0 || y >= List.length l || x < 0 || x >= String.length (List.nth l 0)
let is_in_loop visited (y, x) (dy, dx) =
List.exists
(fun (y1, x1, dy1, dx1) -> y1 == y && x1 == x && dy1 == dy && dx1 == dx)
visited
let positions_visited lines (y, x) =
let rec loop positions (y, x) (dy, dx) =
if is_out_of_bounds lines (y, x) then positions
else
let loop_with_pos = loop ([ (y, x) ] @ positions) in
let next_pos = (y + dy, x + dx) in
if is_out_of_bounds lines next_pos then loop_with_pos next_pos (dy, dx)
else
let next_tile = String.get (List.nth lines (y + dy)) (x + dx) in
if next_tile == '#' then
let new_dy, new_dx = get_direction_change (dy, dx) in
loop_with_pos (y, x) (new_dy, new_dx)
else loop_with_pos (y + dy, x + dx) (dy, dx)
in
loop [] (y, x) (-1, 0)
let check_loop lines (y, x) =
let rec loop positions (y, x) (dy, dx) =
if is_out_of_bounds lines (y, x) then false
else if IntTupleSet.mem (y, x, dy, dx) positions then true
else
let incremented_set = IntTupleSet.add (y, x, dy, dx) positions in
let loop_with_pos = loop incremented_set in
let next_pos = (y + dy, x + dx) in
if is_out_of_bounds lines next_pos then loop_with_pos next_pos (dy, dx)
else
let next_tile = String.get (List.nth lines (y + dy)) (x + dx) in
if next_tile == '#' then
let new_dy, new_dx = get_direction_change (dy, dx) in
loop_with_pos (y, x) (new_dy, new_dx)
else loop_with_pos (y + dy, x + dx) (dy, dx)
in
loop IntTupleSet.empty (y, x) (-1, 0)
let add_obstacle lines (y, x) =
List.mapi
(fun i ->
fun _ ->
if i == y then
let row = List.nth lines y in
let mapped_str =
String.mapi
(fun j -> fun _ -> if j == x then '#' else String.get row j)
row
in
mapped_str
else List.nth lines i)
lines
let solve lines =
let initial_position = find_position lines in
let visited =
positions_visited lines initial_position |> remove_list_duplicates
in
let part1 = List.length visited in
let x_list = List.init (List.nth lines 0 |> String.length) (fun i -> i) in
let y_list = List.init (List.length lines) (fun i -> i) in
(*
#
.#
*)
let part2 =
List.fold_left
(fun acc y ->
acc
+ List.fold_left
(fun acc x ->
let initial_y, initial_x = initial_position in
if
List.exists (fun (y1, x1) -> y1 == y && x1 == x) visited
|| (y == initial_y && x == initial_x)
then (
let new_lines = add_obstacle lines (y, x) in
print_endline (List.nth new_lines 0);
Printf.printf "%d,%d\n" (y + 1) (x + 1);
if check_loop new_lines initial_position then acc + 1 else acc)
else acc)
0 x_list)
0 y_list
in
(part1, part2)