summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Jesus <adbjesus@gmail.com>2025-12-05 16:54:54 +0000
committerAlexandre Jesus <adbjesus@gmail.com>2025-12-05 16:55:24 +0000
commit2088b9e92611c43b6872fedf7d85a033a89f9c3b (patch)
tree846140d2f818c71ded1c44bd447035f7691635ea
parent6d80c94eb7ea8ac0421df0832409b63be7c1246a (diff)
downloadaoc2025-2088b9e92611c43b6872fedf7d85a033a89f9c3b.tar.gz
aoc2025-2088b9e92611c43b6872fedf7d85a033a89f9c3b.zip
Day 4
-rw-r--r--bin/main.ml2
m---------data0
-rw-r--r--lib/day04.ml62
3 files changed, 64 insertions, 0 deletions
diff --git a/bin/main.ml b/bin/main.ml
index 2769553..ce98887 100644
--- a/bin/main.ml
+++ b/bin/main.ml
@@ -32,6 +32,8 @@ let day_part_fn day part =
| 2, 2 -> Day02.part2
| 3, 1 -> Day03.part1
| 3, 2 -> Day03.part2
+ | 4, 1 -> Day04.part1
+ | 4, 2 -> Day04.part2
| _ ->
failwith
(Format.sprintf "Day %d, part %d, has not yet been implemented\n" day
diff --git a/data b/data
-Subproject cfaaae791d91454410a70d895820a2dd38b52ab
+Subproject 4314f8b670ed85271c4c1e16087139622bebc97
diff --git a/lib/day04.ml b/lib/day04.ml
new file mode 100644
index 0000000..c4c3b78
--- /dev/null
+++ b/lib/day04.ml
@@ -0,0 +1,62 @@
+(*
+ * SPDX-FileCopyrightText: Copyright 2025 Alexandre Jesus <https://adbjesus.com>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ *)
+
+let parse_data ch =
+ In_channel.input_all ch
+ |> String.trim
+ |> String.split_on_char '\n'
+ |> List.mapi (fun i s -> (i, s))
+ |> List.to_seq
+ |> Seq.flat_map (fun (i, s) ->
+ String.to_seq s
+ |> Seq.mapi (fun j v -> (j, v = '@'))
+ |> Seq.filter_map (fun (j, p) -> if p then Some ((i, j), 0) else None))
+ |> Hashtbl.of_seq
+
+let neighs =
+ [ (-1, -1); (-1, 0); (-1, 1); (0, -1); (0, 1); (1, -1); (1, 0); (1, 1) ]
+
+let neighs (i, j) = List.map (fun (a, b) -> (i + a, j + b)) neighs
+let count tbl k = (k, neighs k |> List.filter (Hashtbl.mem tbl) |> List.length)
+let counts tbl = Hashtbl.to_seq_keys tbl |> Seq.map (count tbl)
+
+let part1 ch =
+ parse_data ch
+ |> counts
+ |> Seq.filter (fun (_, v) -> v < 4)
+ |> Seq.length
+ |> Printf.printf "%d\n"
+
+let part2 ch =
+ let tbl = parse_data ch |> counts |> Hashtbl.of_seq in
+ let rec fn acc s =
+ let test k =
+ match Hashtbl.find_opt tbl k with
+ | None -> None
+ | Some v when v = 4 ->
+ Hashtbl.remove tbl k;
+ Some k
+ | Some v ->
+ Hashtbl.replace tbl k (v - 1);
+ None
+ in
+ match s with
+ | [] -> acc
+ | h :: t ->
+ neighs h
+ |> List.filter_map test
+ |> List.fold_left (fun (acc, s) k -> (acc + 1, k :: s)) (acc, t)
+ |> fun (acc, s) -> fn acc s
+ in
+ Hashtbl.to_seq tbl
+ |> List.of_seq
+ |> List.filter_map (fun (k, v) ->
+ if v < 4 then (
+ Hashtbl.remove tbl k;
+ Some k)
+ else None)
+ |> (fun s -> fn (List.length s) s)
+ |> Printf.printf "%d\n"