// Record which recipes use which ingredients and vice versa // Beth Katz - October 2008 #include #include #include #include #include #include "LineScanner.h" using namespace std; typedef deque StringDeque; typedef set StringSet; typedef map< string, StringDeque > RecipeType; typedef map< string, StringSet > IngredientType; // given a line, produces a deque of it separated into strings void createList(StringDeque & list, const string & line); // print recipes with their ingredient lists void print(const RecipeType & m); // print the ingredients with the recipes where they're used void print(const IngredientType & ingred); // add recipe name to each ingredient's recipe list void updateIngredients(IngredientType & ingredients, const string & recipeName, const StringDeque & input); int main( ) { string line; RecipeType recipes; IngredientType ingredients; string recipeName; while (getline(cin, line)) { if (line[0] == '?') { print(recipes); print(ingredients); } else { StringDeque input; createList(input, line); if (input.size( ) < 2) { cerr << "Need recipe name and at least one ingredient." << endl; cerr << "Input was: " << line << endl; } else { recipeName = input[0]; input.pop_front( ); recipes[recipeName] = input; updateIngredients(ingredients, recipeName, input); } } } print(recipes); print(ingredients); return 0; } void createList(StringDeque & list, const string & line) { string value; LineScanner input(line); try { while (true) { value = input.nextValue( ); list.push_back(value); } } catch (runtime_error e) { // running out of input is normal; no action } } void print(const RecipeType & r) { RecipeType::const_iterator iter; cout << "====== Current Recipes ======" << endl; for (iter = r.begin( ); iter != r.end( ); ++iter) { cout << iter->first << ": "; for (unsigned i = 0; i < iter->second.size( ); i++) { cout << iter->second[i] << " "; } cout << endl; } cout << endl; } void print(const IngredientType & ingred) { IngredientType::const_iterator iter; StringSet::const_iterator iterS; cout << "====== Ingredients and which Recipes Use Them ======" << endl; for (iter = ingred.begin( ); iter != ingred.end( ); ++iter) { cout << iter->first << ": "; // the key -- ingredient const StringSet & recipeList = iter->second; // the data -- recipe list for (iterS = recipeList.begin( ); iterS != recipeList.end( ); ++iterS) { cout << *iterS << " "; } cout << endl; } cout << endl; } void updateIngredients(IngredientType & ingredients, const string & recipeName, const StringDeque & input) { IngredientType::iterator iter; // pair current; for (unsigned i = 0; i < input.size( ); i++) { iter = ingredients.find(input[i]); if (iter != ingredients.end( )) { // ingredient already in list iter->second.insert(recipeName); // add recipe to its recipe list } else { // ingredient not in list StringSet s; s.insert(recipeName); // create initial recipe list ingredients[ input[i] ] = s; // add ingredient and its recipe list } } }