diff options
| author | Alexandre Jesus <adbjesus@gmail.com> | 2025-12-05 16:54:54 +0000 |
|---|---|---|
| committer | Alexandre Jesus <adbjesus@gmail.com> | 2025-12-05 16:55:24 +0000 |
| commit | 2088b9e92611c43b6872fedf7d85a033a89f9c3b (patch) | |
| tree | 846140d2f818c71ded1c44bd447035f7691635ea | |
| parent | 6d80c94eb7ea8ac0421df0832409b63be7c1246a (diff) | |
| download | aoc2025-2088b9e92611c43b6872fedf7d85a033a89f9c3b.tar.gz aoc2025-2088b9e92611c43b6872fedf7d85a033a89f9c3b.zip | |
Day 4
| -rw-r--r-- | bin/main.ml | 2 | ||||
| m--------- | data | 0 | ||||
| -rw-r--r-- | lib/day04.ml | 62 |
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" |
