diff --git a/src/day8.ml b/src/day8.ml index c4f80b2..fabe7ea 100644 --- a/src/day8.ml +++ b/src/day8.ml @@ -18,7 +18,7 @@ end = struct let at grid point = let x, y = to_tuple point in - let open Option in + let open Option.Infix in let* row = Array.get_safe grid y in Array.get_safe row x ;; @@ -32,60 +32,54 @@ let parse_grid () = Fun.(String.to_seq %> Seq.map (Char.to_string %> int_of_string) %> Seq.to_array) ;; -let rec find_taller_tree grid start_height start step = - let next = Vec2.(start + step) in - match Vec2.at grid next with - | Some height when height < start_height -> find_taller_tree grid start_height next step - | opt -> opt +let solve grid fn = + let grid_h = Array.length grid in + let grid_w = Array.length grid.(0) in + for y = 0 to grid_h - 1 do + for x = 0 to grid_w - 1 do + let start = Vec2.of_tuple (x, y) in + fn start + done + done ;; let part1 () = let grid = parse_grid () in - let grid_h = Array.length grid in - let grid_w = Array.length grid.(0) in let num_visible = ref 0 in - for y = 0 to grid_h - 1 do - for x = 0 to grid_w - 1 do - let start = Vec2.of_tuple (x, y) in - let height = Option.get_exn_or "unreachable" @@ Vec2.at grid start in - let visible = - Vec2.directions - |> List.map @@ find_taller_tree grid height start - |> List.map Option.is_none - |> List.reduce_exn ( || ) - in - if visible then incr num_visible - done - done; + solve grid (fun start -> + let start_height = Option.get_exn_or "unreachable" @@ Vec2.at grid start in + let rec walk_shorter_trees start step = + let next = Vec2.(start + step) in + match Vec2.at grid next with + | Some height when height < start_height -> walk_shorter_trees next step + | opt -> opt + in + let visible = + Vec2.directions + |> List.map @@ walk_shorter_trees start + |> List.map Option.is_none + |> List.reduce_exn ( || ) + in + if visible then incr num_visible); !num_visible ;; -let rec trees_in_view grid start start_height in_view step = - let next = Vec2.(start + step) in - match Vec2.at grid next with - | Some height when height < start_height -> - trees_in_view grid next start_height (in_view + 1) step - | Some _ -> in_view + 1 - | None -> in_view -;; - let part2 () = let grid = parse_grid () in - let grid_h = Array.length grid in - let grid_w = Array.length grid.(0) in let best_score = ref 0 in - for y = 0 to grid_h - 1 do - for x = 0 to grid_w - 1 do - let start = Vec2.of_tuple (x, y) in - let height = Option.get_exn_or "unreachable" @@ Vec2.at grid start in - let score = - Vec2.directions - |> List.map @@ trees_in_view grid start height 0 - |> List.reduce_exn ( * ) - in - if score > !best_score then best_score := score - done - done; + solve grid (fun start -> + let start_height = Option.get_exn_or "unreachable" @@ Vec2.at grid start in + let rec trees_in_view start in_view step = + let next = Vec2.(start + step) in + match Vec2.at grid next with + | Some height when height < start_height -> trees_in_view next (in_view + 1) step + | Some _ -> in_view + 1 + | None -> in_view + in + let score = + Vec2.directions |> List.map @@ trees_in_view start 0 |> List.reduce_exn ( * ) + in + if score > !best_score then best_score := score); !best_score ;;