2024 day 12 part 1.
This commit is contained in:
35
bin/day2412.ml
Normal file
35
bin/day2412.ml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
let find_regions grid =
|
||||||
|
let working = Array.make (Aoc.Grid.length grid) ~-1 in
|
||||||
|
let add_pos region pos perimeter lst =
|
||||||
|
if Aoc.Grid.pos_is_valid grid pos && Aoc.Grid.get_by_pos grid pos = region
|
||||||
|
then (Aoc.Grid.idx_of_pos grid pos :: lst, perimeter - 1)
|
||||||
|
else (lst, perimeter)
|
||||||
|
in
|
||||||
|
let rec scan_pos perimeter area id = function
|
||||||
|
| [] -> (perimeter, area)
|
||||||
|
| idx :: t when working.(idx) <> -1 -> scan_pos perimeter area id t
|
||||||
|
| idx :: t ->
|
||||||
|
working.(idx) <- id;
|
||||||
|
let x, y = Aoc.Grid.pos_of_idx grid idx in
|
||||||
|
let area = succ area in
|
||||||
|
let perimeter = perimeter + 4 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, perimeter = add_pos region (x + 1, y) perimeter t in
|
||||||
|
let t, perimeter = add_pos region (x, y - 1) perimeter t in
|
||||||
|
let t, perimeter = add_pos region (x, y + 1) perimeter t in
|
||||||
|
scan_pos perimeter area id t
|
||||||
|
in
|
||||||
|
let rec impl acc idx id =
|
||||||
|
if idx >= Aoc.Grid.length grid then List.rev acc
|
||||||
|
else
|
||||||
|
let perimeter, area = scan_pos 0 0 id [ idx ] in
|
||||||
|
if area = 0 then impl acc (idx + 1) id
|
||||||
|
else impl ((perimeter, area) :: acc) (idx + 1) (id + 1)
|
||||||
|
in
|
||||||
|
impl [] 0 0
|
||||||
|
|
||||||
|
let part1 grid =
|
||||||
|
find_regions grid |> List.fold_left (fun acc (p, a) -> acc + (p * a)) 0
|
||||||
|
|
||||||
|
let _ = Aoc.main Aoc.Grid.of_file [ (string_of_int, part1) ]
|
Reference in New Issue
Block a user