Day 6
This commit is contained in:
@ -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)
|
||||
|
133
AdventOfCode2024/lib/day_06.ml
Normal file
133
AdventOfCode2024/lib/day_06.ml
Normal 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)
|
Reference in New Issue
Block a user