algorithms

Algorithm implementations
git clone git://git.laack.co/algorithms.git
Log | Files | Refs | README

find-all-possible-recipes-from-given-supplies.py (2595B)


      1 struct Node{
      2   size_t inDegree;
      3   string name;
      4   bool isRecipe;
      5   vector<string> requiredBy;
      6 };
      7 
      8 
      9 class Solution {
     10 public:
     11     vector<string> findAllRecipes(vector<string>& recipes, vector<vector<string>>& ingredients, vector<string>& supplies) {
     12 
     13         // n different recipes (recipes.size())
     14         // ingredients[i] are ingredients to make recipes[i]
     15         // works if we have all of the ingredients in supplies
     16         // a recipe can be an ingredient for other recipes too
     17 
     18         // approach:
     19             // this seems like a topological sort problem
     20             // to add a recipe to the list, all of the priors (ingredients)
     21             // must be in the sorted list.
     22 
     23             // concretely:
     24                 // use khan's algorithm
     25                     // add all vertices with an in-degree of zero to sorted list
     26                     // decrement in-degrees for all nodes they point to
     27                     // repeat process while the # of in-degree nodes is non-zero
     28                     // as we work we might also want a parallel list that tracks
     29                         // the insertion of recipes into our vector to return
     30         
     31         vector<string> canMake = {};
     32         unordered_map<string, Node> graph = {};
     33 
     34         // len(ingredients[i]) >= 1 so we just push supplies to stack for evaluation.
     35         vector<string> stack = {};
     36         for(auto supply: supplies) {
     37             graph[supply] = Node(0, supply, false, {});
     38             stack.push_back(supply);
     39         }
     40 
     41         // since there can be recipe dependence, we can't do the edge tracking here
     42         // basically we might not be able to reference a pre-req here.
     43 
     44         for(auto recipe: recipes) {
     45             graph[recipe] = Node(0, recipe, true, {});
     46         }
     47 
     48         for(size_t i = 0; i < recipes.size(); ++i) {
     49             Node& recipe = graph[recipes[i]];
     50             recipe.inDegree = ingredients[i].size();
     51             for(auto ingredient: ingredients[i]) {
     52                 graph[ingredient].requiredBy.push_back(recipes[i]);
     53             }
     54         }
     55 
     56         while(stack.size() != 0) {
     57 
     58             string current = stack.back();
     59             stack.pop_back();
     60             Node& cn = graph[current];
     61             auto& reqs = cn.requiredBy;
     62 
     63             for(auto rq : reqs) {
     64                 graph[rq].inDegree -= 1;
     65                 if(graph[rq].inDegree == 0) {
     66                     stack.push_back(rq);
     67                     if(graph[rq].isRecipe) {
     68                         canMake.push_back(rq);
     69                     }
     70                 }
     71             }
     72         }
     73 
     74         return canMake;
     75     }
     76 };