2024 day 12 part 2

This commit is contained in:
2024-12-12 09:49:19 +00:00
parent 46755cea34
commit 7e0e6d3770

View File

@@ -1,9 +1,40 @@
let find_regions grid = let get_by_pos_opt grid pos =
if Aoc.Grid.pos_is_valid grid pos then Some (Aoc.Grid.get_by_pos grid pos)
else None
let perimeter grid (x, y) =
let region = Aoc.Grid.get_by_pos grid (x, y) in
0
+ (if get_by_pos_opt grid (x - 1, y) = Some region then 1 else 0)
+ (if get_by_pos_opt grid (x + 1, y) = Some region then 1 else 0)
+ (if get_by_pos_opt grid (x, y + 1) = Some region then 1 else 0)
+ if get_by_pos_opt grid (x, y - 1) = Some region then 1 else 0
let is_corner grid (x, y) (dx, dy) =
let region = Aoc.Grid.get_by_pos grid (x, y) in
if
get_by_pos_opt grid (x + dx, y) <> Some region
&& get_by_pos_opt grid (x, y + dy) <> Some region
then true
else if
get_by_pos_opt grid (x + dx, y) = Some region
&& get_by_pos_opt grid (x, y + dy) = Some region
&& get_by_pos_opt grid (x + dx, y + dy) <> Some region
then true
else false
let corners grid pos =
(if is_corner grid pos (-1, -1) then 1 else 0)
+ (if is_corner grid pos (-1, 1) then 1 else 0)
+ (if is_corner grid pos (1, 1) then 1 else 0)
+ if is_corner grid pos (1, -1) then 1 else 0
let find_regions calc grid =
let working = Array.make (Aoc.Grid.length grid) ~-1 in let working = Array.make (Aoc.Grid.length grid) ~-1 in
let add_pos region pos perimeter lst = let add_pos region pos lst =
if Aoc.Grid.pos_is_valid grid pos && Aoc.Grid.get_by_pos grid pos = region if get_by_pos_opt grid pos = Some region then
then (Aoc.Grid.idx_of_pos grid pos :: lst, perimeter - 1) Aoc.Grid.idx_of_pos grid pos :: lst
else (lst, perimeter) else lst
in in
let rec scan_pos perimeter area id = function let rec scan_pos perimeter area id = function
| [] -> (perimeter, area) | [] -> (perimeter, area)
@@ -12,12 +43,12 @@ let find_regions grid =
working.(idx) <- id; working.(idx) <- id;
let x, y = Aoc.Grid.pos_of_idx grid idx in let x, y = Aoc.Grid.pos_of_idx grid idx in
let area = succ area in let area = succ area in
let perimeter = perimeter + 4 in let perimeter = perimeter + calc grid (x, y) in
let region = Aoc.Grid.get_by_idx grid idx in let region = Aoc.Grid.get_by_idx grid idx in
let t, perimeter = add_pos region (x - 1, y) perimeter t in let t = add_pos region (x - 1, y) t in
let t, perimeter = add_pos region (x + 1, y) perimeter t in let t = add_pos region (x + 1, y) t in
let t, perimeter = add_pos region (x, y - 1) perimeter t in let t = add_pos region (x, y - 1) t in
let t, perimeter = add_pos region (x, y + 1) perimeter t in let t = add_pos region (x, y + 1) t in
scan_pos perimeter area id t scan_pos perimeter area id t
in in
let rec impl acc idx id = let rec impl acc idx id =
@@ -29,7 +60,9 @@ let find_regions grid =
in in
impl [] 0 0 impl [] 0 0
let part1 grid = let part calc grid =
find_regions grid |> List.fold_left (fun acc (p, a) -> acc + (p * a)) 0 find_regions calc grid |> List.fold_left (fun acc (p, a) -> acc + (p * a)) 0
let _ = Aoc.main Aoc.Grid.of_file [ (string_of_int, part1) ] let _ =
Aoc.main Aoc.Grid.of_file
[ (string_of_int, part perimeter); (string_of_int, part corners) ]