Reputation: 1463
We are given a dictionary of recipes, as well as list of raw ingredients;
recipes = {
'axe': {'stick': 1, 'rock': 1, 'tape': 1},
'double_axe': {'axe': 2, 'tape': 1},
'quadruple_axe': {'double_axe': 2, 'tape': 1, 'rock': 2}
}
raw_ingredients = {'rock', 'stick', 'tape'}
The question is; programmatically find number of raw ingredients(of each type) used for each recipe. Please note that raw ingredients only include rock
,tape
, and stick
.
Here is my attempt to solve this question in Python;
def get_ingredients(name, s, l):
s[name]=dict1
#get dictionary for each recipe
k=dict1.keys()
#retrieve the keys
dict2={}
#define empty dictionary to store count of raw ingredients
for i in k:
#loop over the keys
if i in l:
#if key is a raw ingredient, we will increase the count for that corresponding raw ingredient
dict2[i]=dict1[i]
else:
#otherwise call the function recursively
for j in range(0,dict1[i]):
get_ingredients(i, s, l)
Here name
can be either {axe, double_axe,quadruple_axe}
, s
is same as recipes
, and l
is same as raw_ingredients
.
I fully understand that, my code is not complete. It is only my first attempt at the question, and I am trying to get skeleton here. Here are the two key questions I need help with;
quadruple_axe
needs 4 sticks in total.Thanks in advance for help
Upvotes: 0
Views: 787
Reputation: 41872
First, how to keep track of count of the ingredients needed, for instance quadruple_axe needs 4 sticks in total.
Your instinct to use a dictionary to gather the ingredient counts is good:
dict2={}
#define empty dictionary to store count of raw ingredients
But please, put the comment before the line about which it comments, not after.
Second, when do we stop recursing, i.e. what is the base case here?
You handle raw ingredients directly, you recurse on sub recipes. So the recusion naturally stops when you've exhausted all the sub recipes -- you don't have to test for it explicitly.
I recommend that you stop thinking in terms of dict1
and dict2
as well as i
, j
and k
and program in the language of the problem. I also suggest that you use a defaultdict
to collect your final list of raw ingredients, converting it to a generic dict
at the end if you feel the need. But this is optional and just simplifies the code:
from collections import defaultdict
recipes = {
'axe': {'stick': 1, 'rock': 1, 'tape': 1},
'double_axe': {'axe': 2, 'tape': 1},
'quadruple_axe': {'double_axe': 2, 'tape': 1, 'rock': 2}
}
raw_ingredients = {'rock', 'stick', 'tape'}
def count_raw_ingredients(recipe):
ingredients = defaultdict(int)
for ingredient, amount in recipes[recipe].items():
if ingredient in raw_ingredients:
ingredients[ingredient] += amount
else:
for subingredient, subamount in count_raw_ingredients(ingredient).items():
ingredients[subingredient] += amount * subamount
return dict(ingredients)
print(count_raw_ingredients('quadruple_axe'))
OUTPUT
> python3 test.py
{'stick': 4, 'rock': 6, 'tape': 7}
>
Upvotes: 1
Reputation: 77857
Your base case is when the ingredient name does not appear as a recipe label.
You recur on the three axe
types; you stop on stick
, rock
, or tape
.
You can keep track by passing back a dict of base ingredient counts. For instance, a check for "double-axe" will return the computational roll-up for 2 * {'stick': 1, 'rock': 1, 'tape': 1} + {'tape': 1}
. You should be able to derive that code for yourself, or look it up here with something like "Python add values two dicts".
Upvotes: 0