关键词 > CSSE1001/CSSE7030
CSSE1001/CSSE7030 Semester 1, 2023 Assignment 1
发布时间:2023-03-10
Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit
Recipes and Ingredients: Shopamania
COOK1001
Assignment 1
Semester 1, 2023
CSSE1001/CSSE7030
Updated: 03/03/23 15:44
Due date: 24 March 2023, 16:00 GMT+10
1 Introduction
You are a single parent with four hungry children and the weekly grocery shop is becoming difficult. Luckily, you know a bit of Python and can write a program that generates a shopping list based on what recipes are going to be prepared that week.
2 Getting Started
Download a1 .zip from Blackboard — this archive contains the necessary files to start this as- signment. Once extracted, the a1 .zip archive will provide the following files:
a1 .py This is the only file you will submit and is where you write your code. Do not make changes to any other files.
constants .py Do not modify or submit this file, this file also contains some constants that will be useful in your implementation. In addition to these, you are encouraged to create your own constants in a1 .py where possible. This is where you will find some recipes that can be added to the recipe book as well.
Note: You are not permitted to add any import statements to a1 .py. Doing so will result in a deduction of up to 100% of your mark.
3 Terminology
In the context of this assignment:
recipe name: str represents the name of a recipe. Note: Recipe names should only contain lowercase letters from the English alphabet without any numbers or special characters.
recipe: tuple[str, str] is a tuple containing two str’s. The first str in the tuple rep- resents the name of the recipe. The second str contains all the ingredients in the form of 'amount measure ingredient_name', e.g. '115 g Nuttelex' which represents 115 grams of Nuttelex. When multiple ingredients are present, they are separated by a sin- gle comma. Note that there is no space. e.g. '115 g Nuttelex,50 g sugar' have a look at constants .py for examples.
recipes: list[tuple[str, str]] is a list of recipes. Each recipe follows the format described above. Duplicates can exist.
ingredient detail: tuple[float, str, str] , is a tuple containing information of a single ingredient. (amount, measure, ingredient name), e.g. (115 .0, 'g', 'Nuttelex').
cookbook is a collection of all available recipes and you may use whatever type you feel is appro- priate for it. Duplicates do not exist in the cookbook.
This section provides an overview of the interaction. Where prompts and outputs are not explicitly mentioned in this section, please see Section 5.
4.1 Interaction loop
At the beginning of the interaction, the user is prompted with the message
Please enter a command:
(note the trailing space) to choose a command. Once a command is entered the user should be prompted again. The valid commands are outlined in Table 1.
Throughout the interaction, the user may add to or remove from the cookbook. They can also add to or remove from the list of recipes as well. You may assume that your program will not be tested for invalid inputs that do not match the expected commands in Table 1. The prompt should repeat until the user quit by entering the "Q" or "q" action.
Description |
||
"H" or "h" |
Display a help message. |
|
"Q" or "q" |
Quit. |
|
"add {recipe}" |
adds a recipe to the list of recipes. |
|
"rm {recipe}" |
removes a recipe from the collection. |
|
"rm {ingredient name} {amount}" |
removes an ingredient from the shopping list. |
|
"g" or "G" |
generates a shopping recipes. |
list based on the list of |
"ls" |
list all recipes in shopping cart. |
|
"ls -a" |
list all available recipes. |
|
"ls -s" |
display shopping list. |
|
"mkrec" |
creates a recipe. |
Table 1: Potential command that user can choose. {recipe} denotes that the name of recipe should be provided. Values not surrounded by braces should be taken as string literals.
This section outlines functions you are required to implement in your solution (in a1 .py only). You are awarded marks for the number of tests passed by your functions when they are tested independently. Thus an incomplete assignment with some working functions may well be awarded more marks than a complete assignment with faulty functions. Your program must operate exactly as specified. In particular, your program’s output must match exactly with the expected output. Your program will be marked automatically so minor differences in output (such as whitespace or casing) will cause tests to fail resulting in a zero mark for that test.
Each function is accompanied with some examples for usage to help you start your own testing. You should also test your functions with other values to ensure they operate according to the descriptions.
5.1 Required Functions
The following functions must be implemented in a1 .py. They have been listed in order of increas- ing difficulty. It is highly recommended that you do not begin work on a later function until each of the preceding functions can at least behave as per the shown examples. You may implement addi- tional functions if you think they will help with your logic or make your code easier to understand.
Your first task should be writing function headers for each of these required functions into a1 .py. For example, you could write
def get_recipe_name(recipe: tuple[str, str]) -> str
""" Return . . .
>>> get_recipe_name( . . .)
"""
return
in your file and then add usage examples and docstrings based on what you read below. Then completing the assignment means filling in each function properly as is done with ShiFoo.
5.1.1 num hours() -> float
This function should return the number of hours you estimate you spent (or have spent so far) on the assignment, as a float. You will not be marked differently for spending more or less time on the assignment. The purpose of this function is to enable you to verify that you understand how to submit to Gradescope as soon as possible, and to allow us to gauge difficulty level of this assignment in order to provide the best possible assistance.
Ensure this function passes the relevant test on Gradescope as soon as possible. If the Gradescope tests have been released, you must ensure this function passes the relevant test before seeking help regarding Gradescope issues for any of the later functions. See Section 7.3 for instructions on how to submit your assignment to Gradescope.
5.1.2 get recipe name(recipe: tuple[str, str]) -> str
Returns the name of the recipe.
Example:
>>> get_recipe_name(('chocolate peanut butter banana shake',
'1 large banana,240 ml almond milk'))
'chocolate peanut butter banana shake'
>>> get_recipe_name(('cinnamon rolls',
'480 ml almond milk,170 g Nuttelex'))
'cinnamon rolls'
5.1.3 parse ingredient(raw ingredient detail: str) -> tuple[float, str, str] Return the ingredient breakdown from the details amount, measure, and ingredient.
Example:
>>> parse_ingredient('0 .5 tsp coffee granules')
(0 .5, 'tsp', 'coffee granules')
>>> parse_ingredient('1 large banana')
(1 .0, 'large', 'banana')
5.1.4 create recipe() -> tuple[str, str]
Return a recipe in the tuple[str, str] format after a series of prompting. The recipe name is prompted first followed by continuous ingredient prompting until an empty string is entered (enter or return key press with no text).
Example:
>>> create_recipe()
Please enter the recipe name: peanut butter
Please enter an ingredient: 300 g peanuts
Please enter an ingredient: 0 .5 tsp salt
Please enter an ingredient: 2 tsp oil
Please enter an ingredient:
('peanut butter', '300 g peanuts,0 .5 tsp salt,2 tsp oil')
5.1.5 recipe ingredients(recipe: tuple[str, str]) -> tuple[tuple[float, str, str]]
Return the ingredients of a recipe amount, measure, and ingredient. This transforms a given recipe from the string form into the tuples form.
Example:
>>> recipe_ingredients(('peanut butter',
'300 g peanuts,0 .5 tsp salt,2 tsp oil'))
((300 .0, 'g', 'peanuts'), (0 .5, 'tsp', 'salt'), (2 .0, 'tsp', 'oil'))
5.1.6 add recipe(new recipe: tuple[str, str],
recipes: list[tuple[str, str]]) -> None
Add a given recipe, new_recipe, into the list of recipes. Hint: This function doesn’t return anything. Recall list mutability.
Example:
>>> recipes = []
>>> recipe = ('peanut butter', '300 g peanuts,0 .5 tsp salt,2 tsp oil') >>> add_recipe(recipe, recipes)
>>> recipes
[('peanut butter', '300 g peanuts,0 .5 tsp salt,2 tsp oil')]
>>> add_recipe(recipe, recipes)
>>> recipes
[('peanut butter', '300 g peanuts,0 .5 tsp salt,2 tsp oil'), ('peanut butter', '300 g peanuts,0 .5 tsp salt,2 tsp oil')]
5.1.7 find recipe(recipe name: str,
recipes: list[tuple[str, str]]) -> tuple[str, str] | None
Return a recipe or None. This function should attempt to find the recipe by the given recipe name within the list of recipes. If the recipe can not be found then this function should return None.
Example:
>>> recipes = [('peanut butter', '300 g peanuts,0 .5 tsp salt,2 tsp oil')] >>> find_recipe('peanut butter', recipes)
('peanut butter', '300 g peanuts,0 .5 tsp salt,2 tsp oil')
>>> find_recipe('cinnamon rolls', recipes)
>>> print(find_recipe('cinnamon rolls', recipes))
None
5.1.8 remove recipe(name: str, recipes: list[tuple[str, str]]) -> None
Remove a recipe from the list of recipes given the name of a recipe. If the recipe name does not match any of the recipes within the list of recipes then nothing happens.
Example:
>>> recipes = [('peanut butter', '300 g peanuts,0 .5 tsp salt,2 tsp oil'), ('cinnamon rolls', '480 ml almond milk,115 g Nuttelex,50 g sugar,7 g active dry yeast,5 .5 cup flour,1 tsp salt,170 g Nuttelex,165 g brown sugar,2 tbsp cinnamon,160 g powdered sugar,30 ml almond milk,0 .5 tsp vanilla extract')]
>>> remove_recipe('brownie', recipes)
>>> recipes
[('peanut butter', '300 g peanuts,0 .5 tsp salt,2 tsp oil'), ('cinnamon rolls', '480 ml almond milk,115 g Nuttelex,50 g sugar,7 g active dry yeast,5 .5 cup flour,1 tsp salt,170 g Nuttelex,165 g brown sugar,2 tbsp cinnamon,160 g powdered sugar,30 ml almond milk,0 .5 tsp vanilla extract')]
>>> remove_recipe('cinnamon rolls', recipes)
>>> recipes
[('peanut butter', '300 g peanuts,0 .5 tsp salt,2 tsp oil')]
5.1.9 get ingredient amount(ingredient: str, recipe: tuple[str, str]) -> tuple[float,
str] | None
Return the amount and measure of a certain ingredient as a tuple[float, str] given the ingre- dient name as a str and a recipe. If the ingredient doesn’t exist then nothing happens.
Example:
>>> recipe = ('peanut butter', '300 g peanuts,0 .5 tsp salt,2 tsp oil') >>> get_ingredient_amount('peanuts', recipe)
(300 .0, 'g')
>>> get_ingredient_amount('soy beans', recipe)
5.1.10 add to shopping list(ingredient details: tuple[float, str, str],
shopping list: list[tuple[float, str, str] | None]) -> None
Add an ingredient to the shopping list which could be empty or could contain tuples of ingredient details. If the ingredient being added already exist within the shopping list then the amount should be combined. If the ingredient does not exist then it can be added without any calcula- tions.
Note: It can be assumed that the measure is consistent for all ingredients of the same name. In addition, ingredient_details contains all the information about the ingredient being added to the shopping list. Also, the order does not matter.
Example:
>>> shopping_list = [(300 .0, 'g', 'peanuts'), (0 .5, 'tsp', 'salt'),
(2 .0, 'tsp', 'oil')]
>>> add_to_shopping_list((1000 .0, 'g', 'tofu'), shopping_list)
>>> shopping_list
[(300 .0, 'g', 'peanuts'), (0 .5, 'tsp', 'salt'), (2 .0, 'tsp', 'oil'), (1000 .0, 'g', 'tofu')]
>>> add_to_shopping_list((1200 .0, 'g', 'peanuts'), shopping_list)
>>> shopping_list
[(1500 .0, 'g', 'peanuts'), (0 .5, 'tsp', 'salt'), (2 .0, 'tsp', 'oil'), (1000 .0, 'g', 'tofu')]
>>> add_to_shopping_list((8000 .0, 'g', 'tofu'), shopping_list)
>>> shopping_list
[(1500 .0, 'g', 'peanuts'), (0 .5, 'tsp', 'salt'), (2 .0, 'tsp', 'oil'), (9000 .0, 'g', 'tofu')]
5.1.11 remove from shopping list(ingredient name: str, amount: float, shopping list:
list) -> None
Remove a certain amount of an ingredient, with the given ingredient_name, from the shopping_list. If the ingredient exists in the shopping_list then the amount given as the parameter of this func-tion should be subtracted from the amount that exists in the shopping_list. The ingredient should be removed from the shopping list altogether if the amount goes below 0.
Example:
>>> shopping_list = [(1500 .0, 'g', 'peanuts'), (0 .5, 'tsp', 'salt'), (2 .0, 'tsp', 'oil'), (9000 .0, 'g', 'tofu'), (100 .0, 'g', 'sugar'), (50 .0, 'g', 'tomato sauce'), (120 .0, 'g', 'rice'),
(920 .0, 'g', 'ice cream')]
>>> remove_from_shopping_list('ice cream', 500 .0, shopping_list)
>>> shopping_list
[(1500 .0, 'g', 'peanuts'), (0 .5, 'tsp', 'salt'), (2 .0, 'tsp', 'oil'), (9000 .0, 'g', 'tofu'), (100 .0, 'g', 'sugar'), (50 .0, 'g', 'tomato
sauce'), (120 .0, 'g', 'rice'), (420 .0, 'g', 'ice cream')]
>>> remove_from_shopping_list('sugar', 500 .0, shopping_list)
>>> shopping_list
[(1500 .0, 'g', 'peanuts'), (0 .5, 'tsp', 'salt'), (2 .0, 'tsp', 'oil'), (9000 .0, 'g', 'tofu'), (50 .0, 'g', 'tomato sauce'), (120 .0, 'g',
'rice'), (420 .0, 'g', 'ice cream')] >>> remove_from_shopping_list('ice cream', 9000 .0, shopping_list)
>>> shopping_list
[(1500 .0, 'g', 'peanuts'), (0 .5, 'tsp', 'salt'), (2 .0, 'tsp', 'oil'), (9000 .0, 'g', 'tofu'), (50 .0, 'g', 'tomato sauce'), (120 .0, 'g', 'rice')]
5.1.12 generate shopping list(recipes: list[tuple[str, str]])
-> list[tuple[float, str, str]]
Return a list of ingredients, (amount, measure, ingredient_name), given a list of recipes.
Example:
>>> shopping_list = generate_shopping_list([PEANUT_BUTTER,
MUNG_BEAN_OMELETTE])
>>> shopping_list
[(300 .0, 'g', 'peanuts'), (1 .0, 'tsp', 'salt'), (3 .0, 'tsp', 'oil'), (1 .0, 'cup', 'mung bean'), (0 .75, 'tsp', 'pink salt'), (0 .25, 'tsp', 'garlic powder'), (0 .25, 'tsp', 'onion powder'), (0 .125, 'tsp', 'pepper'), (0 .25, 'tsp', 'turmeric'), (1 .0, 'cup', 'soy milk')]
>>> shopping_list = generate_shopping_list([PEANUT_BUTTER, PEANUT_BUTTER, MUNG_BEAN_OMELETTE])
>>> shopping_list
[(600 .0, 'g', 'peanuts'), (1 .5, 'tsp', 'salt'), (5 .0, 'tsp', 'oil'),
(1 .0, 'cup', 'mung bean'), (0 .75, 'tsp', 'pink salt'), (0 .25, 'tsp', 'garlic powder'), (0 .25, 'tsp', 'onion powder'), (0 .125, 'tsp', 'pepper'), (0 .25, 'tsp', 'turmeric'), (1 .0, 'cup', 'soy milk')]
5.1.13 display ingredients(shopping list: list[tuple[float, str, str]]) -> None
Print the given shopping list in any order you wish. CSSE7030 students must display the shopping list alphabetically based on the name of the ingredients. See example in Appendix.
Note: The amount of spaces changes depending on how long the longest text is. The order does not matter.
Example:
>>> display_ingredients([(1 .0, 'large', 'banana'), (0 .5, 'cup', 'ice'),]) | 1 .0 | large | banana |
| 0 .5 | cup | ice |
>>> display_ingredients([(1 .0, 'large', 'banana'),
(2 .0, 'tbsp', 'peanut butter'),
(2 .0, 'pitted', 'dates'),
(1 .0, 'tbsp', 'cacao powder'),
(240 .0, 'ml', 'almond milk'),
(0 .5, 'cup', 'ice'),
(1 .0, 'tbsp', 'cocao nibs'),
(1 .0, 'tbsp', 'flax seed')])
| | | | | | | |
1 .0 2 .0 2 .0 1 .0 240 .0 0 .5 1 .0 1 .0
| | | | | | |
large tbsp pitted tbsp ml cup tbsp tbsp |
|
banana peanut butter dates cacao powder almond milk ice cocao nibs flax seed |
| | | | | | |
Here is the output again with visile spaces.
|␣␣␣1 .0␣|␣␣large␣␣|␣banana␣␣␣␣␣␣␣␣␣|
|␣␣␣2 .0␣|␣␣tbsp␣␣␣|␣peanut␣butter␣␣|
|␣␣␣2 .0␣|␣pitted␣␣|␣dates␣␣␣␣␣␣␣␣␣␣|
|␣␣␣1 .0␣|␣␣tbsp␣␣␣|␣cacao␣powder␣␣␣|
|␣240 .0␣|␣␣␣ml␣␣␣␣|␣almond␣milk␣␣␣␣|
|␣␣␣0 .5␣|␣␣␣cup␣␣␣|␣ice␣␣␣␣␣␣␣␣␣␣␣␣|
|␣␣␣1 .0␣|␣␣tbsp␣␣␣|␣cocao␣nibs␣␣␣␣␣|
|␣␣␣1 .0␣|␣␣tbsp␣␣␣|␣flax␣seed␣␣␣␣␣␣|
5.1.14 sanitise command(command: str) -> str
Return a standardised command to all lower-case and no leading or trailing white spaces removing any numbers from the string.
Example:
>>> sanitise_command('add 'add chocolate brownies' >>> sanitise_command('add 'add chocolate brownies' >>> sanitise_command('add 'add chocolate brownies'
chocolate brownies')
c4hocolate Brownies')
chocolate Brownies 5')
>>> sanitise_command('add chocolate Brownies ')
'add chocolate brownies'
5.1.15 main() -> None
The main function should be called when the file is run, and coordinates the overall interaction. The main function should utilize other functions you have written. You should consider writing extra helper functions. In the provided a1 .py, the function definition for main has already been provided, and the if name == main : block will ensure that the code in the main function is run when your a1 .py file is run. Do not call your main function outside of this block, and do not call any other function outside this block unless you are calling them from within the body of another function. The output from your main function (including prompts) must exactly match the expected output. Running the sample tests will give you a good idea of whether your prompts and other outputs are correct. See Section 6 for example usage.
Section 4 describes how the program runs. The basic steps that must be implemented by this function are as follows:
1. Prompt user for command.
2. Displays certain information depending on what command is entered.
3. Until the quit command is entered.
The following section provides extended instances of user interaction to demonstrate completed program behaviour.
Example 1
Please enter a command: h
H or h: Help
mkrec: creates a recipe, add to cook book .
add {recipe}: adds a recipe to the collection .
rm {recipe}: removes a recipe from the collection .
rm -i {ingredient_name} {amount}: removes ingredient from shopping list . ls: list all recipes in shopping cart .
ls -a: list all available recipes in cook book .
ls -s: display shopping list .
g or G: generates a shopping list .
Q or q: Quit .