diff --git a/bin/day2423.ml b/bin/day2423.ml index 68eb174..7171595 100644 --- a/bin/day2423.ml +++ b/bin/day2423.ml @@ -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 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 = StringMap.to_list connections @@ -61,27 +61,6 @@ let part1 connections = |> find_rings [] StringSet.empty connections |> 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 computers in a star network (that is for every pair of elements in the list 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 a (StringMap.find a connections)] must return [false]. *) let find_max_set connections = - let rec impl max_lst = function - | [] -> max_lst - | (k, v) :: t -> - impl - (search_candidate max_lst connections [ k ] (StringSet.to_list v)) - t + let rec search_candidate max_lst current candidates = + (* recursion invariant: all nodes in the list [current] are in a clique with + each other. [current] unioned with any individual element of + [candidates] is also a valid clique. *) + 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 current' candidates' in + search_candidate max_lst current t in - impl [] (StringMap.to_list connections) + StringMap.to_list connections |> List.map fst |> search_candidate [] [] let part2 connections = find_max_set connections |> List.sort compare |> String.concat ","