2024 day 12 part 2
This commit is contained in:
@@ -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) ]
|
||||||
|
Reference in New Issue
Block a user