From dbc723e2d13593277b317b74cc81d400aae0b573 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 10 Dec 2024 09:06:07 +0000 Subject: [PATCH] 2024 day 10 --- bin/day2410.ml | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ bin/dune | 6 +++-- 2 files changed, 65 insertions(+), 2 deletions(-) create mode 100644 bin/day2410.ml diff --git a/bin/day2410.ml b/bin/day2410.ml new file mode 100644 index 0000000..6ffdfe5 --- /dev/null +++ b/bin/day2410.ml @@ -0,0 +1,61 @@ +type grid = { grid : string; width : int; height : int } + +let grid_of_file fname = + let strs = Aoc.strings_of_file fname in + let grid = List.fold_left String.cat "" strs in + let width = String.length (List.hd strs) in + let height = String.length grid / width in + { grid; width; height } + +let grid_length grid = String.length grid.grid +let grid_get_by_idx grid idx = grid.grid.[idx] +let grid_get_by_pos grid (x, y) = grid.grid.[x + (y * grid.width)] +let grid_pos_of_idx grid idx = (idx mod grid.width, idx / grid.width) + +let grid_pos_is_valid grid (x, y) = + x >= 0 && y >= 0 && x < grid.width && y < grid.height + +let next_char ch = Char.chr (1 + Char.code ch) +let ten = next_char '9' +let one = '1' + +let find_trail grid pos0 = + let add_pos lst pos digit = + if grid_pos_is_valid grid pos && grid_get_by_pos grid pos = digit then + pos :: lst + else lst + in + let add_poses lst (x, y) digit = + let lst = add_pos lst (x - 1, y) digit in + let lst = add_pos lst (x + 1, y) digit in + let lst = add_pos lst (x, y - 1) digit in + let lst = add_pos lst (x, y + 1) digit in + lst + in + let rec find_next acc digit = function + | [] -> acc + | h :: t -> find_next (add_poses acc h digit) digit t + in + let rec impl acc digit = + if digit = ten then acc else impl (find_next [] digit acc) (next_char digit) + in + impl [ pos0 ] one + +let find_trails grid = + let rec impl acc idx = + if idx >= grid_length grid then acc + else if grid_get_by_idx grid idx <> '0' then impl acc (idx + 1) + else (* grid_get_by_idx grid idx = 0 *) + impl (find_trail grid (grid_pos_of_idx grid idx) :: acc) (idx + 1) + in + impl [] 0 |> List.rev + +let part1 grid = + find_trails grid + |> List.map (List.sort_uniq compare) + |> List.map List.length |> List.fold_left ( + ) 0 + +let part2 grid = + find_trails grid |> List.map List.length |> List.fold_left ( + ) 0 + +let _ = Aoc.main grid_of_file [ (string_of_int, part1); (string_of_int, part2) ] diff --git a/bin/dune b/bin/dune index 6b6c429..a607d83 100644 --- a/bin/dune +++ b/bin/dune @@ -8,7 +8,8 @@ day2406 day2407 day2408 - day2409) + day2409 + day2410) (names day2401 day2402 @@ -18,5 +19,6 @@ day2406 day2407 day2408 - day2409) + day2409 + day2410) (libraries str aoc))