Another tidy up of 2024 day 23

Notice that part 2's recursive function works from the top level
onwards.
This commit is contained in:
2024-12-23 14:55:24 +00:00
parent 7f0977ce1d
commit 7286ea2486

View File

@@ -53,7 +53,7 @@ let rec find_rings acc visited connections = function
(** [starts_with_t set] returns true if any member of [set] starts with the (** [starts_with_t set] returns true if any member of [set] starts with the
letter ['t']. *) letter ['t']. *)
let starts_with_t set = StringSet.exists (fun x -> x.[0] = 't') set let starts_with_t = StringSet.exists (fun x -> x.[0] = 't')
let part1 connections = let part1 connections =
StringMap.to_list connections StringMap.to_list connections
@@ -61,27 +61,6 @@ let part1 connections =
|> find_rings [] StringSet.empty connections |> find_rings [] StringSet.empty connections
|> List.filter starts_with_t |> List.length |> string_of_int |> List.filter starts_with_t |> List.length |> string_of_int
(** [search_candidate max_lst connections current candidates] searches for the
longest star network that contains all the computers in [current] and maybe
some of the elements of [candidates].
[max_lst] is the biggest network found so far. [connections] is the map of
computers to direct connections.
The initial call should look something like:
[search_candidate [] connections k (StringSet.to_list (StringMap.find k
connections))] *)
let rec search_candidate max_lst connections current candidates =
match candidates with
| [] -> if List.length current > List.length max_lst then current else max_lst
| h :: t ->
let map = StringMap.find h connections in
let current' = h :: current in
let candidates' = List.filter (Fun.flip StringSet.mem map) candidates in
let max_lst = search_candidate max_lst connections current' candidates' in
search_candidate max_lst connections current t
(** [find_max_set connections] returns a list containing the largest number of (** [find_max_set connections] returns a list containing the largest number of
computers in a star network (that is for every pair of elements in the list computers in a star network (that is for every pair of elements in the list
there is a connection between them). there is a connection between them).
@@ -92,14 +71,21 @@ let rec search_candidate max_lst connections current candidates =
[StringSet.mem b (StringMap.find a connections)]. Note that [StringSet.mem b (StringMap.find a connections)]. Note that
[StringSet.mem a (StringMap.find a connections)] must return [false]. *) [StringSet.mem a (StringMap.find a connections)] must return [false]. *)
let find_max_set connections = let find_max_set connections =
let rec impl max_lst = function let rec search_candidate max_lst current candidates =
| [] -> max_lst (* recursion invariant: all nodes in the list [current] are in a clique with
| (k, v) :: t -> each other. [current] unioned with any individual element of
impl [candidates] is also a valid clique. *)
(search_candidate max_lst connections [ k ] (StringSet.to_list v)) match candidates with
t | [] ->
if List.length current > List.length max_lst then current else max_lst
| h :: t ->
let map = StringMap.find h connections in
let current' = h :: current in
let candidates' = List.filter (Fun.flip StringSet.mem map) candidates in
let max_lst = search_candidate max_lst current' candidates' in
search_candidate max_lst current t
in in
impl [] (StringMap.to_list connections) StringMap.to_list connections |> List.map fst |> search_candidate [] []
let part2 connections = let part2 connections =
find_max_set connections |> List.sort compare |> String.concat "," find_max_set connections |> List.sort compare |> String.concat ","