diff --git a/AdventOfCode2024/bin/main.ml b/AdventOfCode2024/bin/main.ml index 06dbb1d..f12a03e 100644 --- a/AdventOfCode2024/bin/main.ml +++ b/AdventOfCode2024/bin/main.ml @@ -13,7 +13,7 @@ let read_lines name = let () = print_endline "\nAdvent of Code 2024"; let part1, part2 = - read_lines "./inputs/03.txt" |> AdventOfCode2024.Day_03.solve + read_lines "./inputs/04.txt" |> AdventOfCode2024.Day_04.solve in Printf.printf "Part 1: %s\nPart 2: %s\n" (string_of_int part1) (string_of_int part2) diff --git a/AdventOfCode2024/lib/day_04.ml b/AdventOfCode2024/lib/day_04.ml new file mode 100644 index 0000000..0d0007b --- /dev/null +++ b/AdventOfCode2024/lib/day_04.ml @@ -0,0 +1,93 @@ +let check_at grid x y = + if x < 0 || x >= Array.length grid.(0) || y < 0 || y >= Array.length grid then + None + else Some grid.(y).(x) + +let get_next_char c = + match c with + | 'M' -> 'A' + | 'A' -> 'S' + | _ -> raise (Invalid_argument "cant put this here") + +let rec check_work_in_direction grid x y starting_char direction path = + let dx, dy = direction in + let grid_char = check_at grid (x + dx) (y + dy) in + match grid_char with + | None -> 0 + | Some c -> + if c != starting_char then 0 + else if c == 'S' then 1 + else + check_work_in_direction grid (x + dx) (y + dy) + (get_next_char starting_char) + direction + ([ (x + dx, y + dy) ] @ path) + +let is_char op cc = match op with None -> false | Some c -> c == cc + +let check_word_part2 grid x y = + let grid_char = check_at grid x y in + match grid_char with + | None -> false + | Some 'A' -> + let top_left = check_at grid (x - 1) (y - 1) in + let top_right = check_at grid (x + 1) (y - 1) in + let bottom_left = check_at grid (x - 1) (y + 1) in + let bottom_right = check_at grid (x + 1) (y + 1) in + + let is_back_diagal_mas = + (is_char top_left 'S' && is_char bottom_right 'M') + || (is_char top_left 'M' && is_char bottom_right 'S') + in + + let is_forward_diagal_mas = + (is_char top_right 'S' && is_char bottom_left 'M') + || (is_char top_right 'M' && is_char bottom_left 'S') + in + + is_back_diagal_mas && is_forward_diagal_mas + | Some _ -> false + +let check_word grid x y = + let grid_char = check_at grid x y in + let curried_check = check_work_in_direction grid x y 'M' in + match grid_char with + | None -> 0 + | Some 'X' -> + curried_check (-1, -1) [ (x, y) ] + + curried_check (0, -1) [ (x, y) ] + + curried_check (1, -1) [ (x, y) ] + + curried_check (-1, 0) [ (x, y) ] + + curried_check (1, 0) [ (x, y) ] + + curried_check (-1, 1) [ (x, y) ] + + curried_check (0, 1) [ (x, y) ] + + curried_check (1, 1) [ (x, y) ] + | Some _ -> 0 + +let solve lines = + let grid = + Array.init (List.length lines) (fun i -> + Array.init + (String.length (List.nth lines 0)) + (fun j -> String.get (List.nth lines i) j)) + in + + let x_list = List.init (Array.length grid.(0)) (fun i -> i) in + let y_list = List.init (Array.length grid) (fun i -> i) in + + let part1 = + List.fold_left + (fun acc y -> + acc + List.fold_left (fun acc x -> acc + check_word grid x y) 0 x_list) + 0 y_list + in + let part2 = + List.fold_left + (fun acc y -> + acc + + List.fold_left + (fun acc x -> acc + if check_word_part2 grid x y then 1 else 0) + 0 x_list) + 0 y_list + in + (part1, part2)