diff --git a/bin/day2421.ml b/bin/day2421.ml index cd32328..9855db4 100644 --- a/bin/day2421.ml +++ b/bin/day2421.ml @@ -74,51 +74,37 @@ let find_paths (sx, sy) (fx, fy) = in result +(** [cartesian f initial_acc lst lst'] calls [f acc h h'] for the cross-product + of all elements [h], [h'] in [lst] and [lst']. [acc] is updated in each call + with the result of all previous calls to [f]. The result is the final [acc]. +*) +let cartesian f initial_acc lst lst' = + let rec impl' acc h = function + | [] -> acc + | h' :: t' -> impl' (f acc h h') h t' + in + let rec impl acc = function + | [] -> acc + | h :: t -> impl (impl' acc h lst') t + in + impl initial_acc lst + (** [routes pos_of_grid locs] returns a map of [(start, finish)] pairs mapping to a list of paths for getting to that route. [locs] are the locations on the grid to investiagte. [pos_of_grid] gives the location of each of the [locs]. The returned map contains routes from each element in [locs] to every element. *) let routes pos_of_grid locs = - let rec impl acc pos = - let start = pos_of_grid pos in - function - | [] -> acc - | h :: t -> - impl - (CharPairMap.add (pos, h) (find_paths start (pos_of_grid h)) acc) - pos t + let impl acc h h' = + CharPairMap.add (h, h') (find_paths (pos_of_grid h) (pos_of_grid h')) acc in - let rec impl' acc = function - | [] -> acc - | h :: t -> impl' (impl acc h locs) t - in - impl' CharPairMap.empty locs - -(** Elements on the number grid *) -let num_grid = [ '0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9'; 'A' ] - -(** Routes between positions on the number grid *) -let num_routes = routes pos_of_numeric_grid num_grid - -(** Elements on the direction grid *) -let dir_grid = [ '<'; '>'; 'v'; '^'; 'A' ] - -(** Routes between positions on the direction grid. *) -let dir_routes = routes pos_of_dir_grid dir_grid + cartesian impl CharPairMap.empty locs locs (** [initial_cost_map grid] returns a map for the initial costs (1) of moving between different positions on [grid]. *) let initial_cost_map grid = - let rec impl' acc f = function - | [] -> acc - | h :: t -> impl' (CharPairMap.add (f, h) 1 acc) f t - in - let rec impl acc = function - | [] -> acc - | h :: t -> impl (impl' acc h grid) t - in - impl CharPairMap.empty grid + let update acc h h' = CharPairMap.add (h, h') 1 acc in + cartesian update CharPairMap.empty grid grid (** [calc_cost cost_map steps] calculates the cost of following [steps]. [cost_map] gives the cost of moving between each position. *) @@ -142,13 +128,17 @@ let get_next_level_costs route_map cost_map = (** [min_code_cost count code] returns the number of buttons a human needs to press to get [code] entered when indirected through [count] robots. *) let min_code_cost count code = - let number_costs = + let num_grid = [ '0'; '1'; '2'; '3'; '4'; '5'; '6'; '7'; '8'; '9'; 'A' ] in + let num_routes = routes pos_of_numeric_grid num_grid in + let dir_grid = [ '<'; '>'; 'v'; '^'; 'A' ] in + let dir_routes = routes pos_of_dir_grid dir_grid in + let costs = Aoc.apply_n count (get_next_level_costs dir_routes) (initial_cost_map dir_grid) in - let number_costs = get_next_level_costs num_routes number_costs in - calc_cost number_costs code + let costs = get_next_level_costs num_routes costs in + calc_cost costs code (** [get_code_complexity count code] returns the complexity of a given code when there are [count] robots involved. *)