本周的课堂练习将继续加深你对字典的掌握!
受疫情期间刷剧和做饭的启发,Parth 和 Peter 决定开一家面包店。为了节省成本,他们希望尽可能自动化库存管理。多亏了106A课程,他们觉得可以用字典来帮忙。
所有可用的原料都存储在pantry
字典中,键为原料名,值为重量(当然他们使用公制单位),例如:
pantry = {
'flour': 400,
'sugar': 300,
'salt': 10,
'chocolate': 150
}
每个食谱也用字典存储,例如以下这个不太令人兴奋的配方:
recipe = {
'flour': 200,
'salt': 2.5
}
(如你所见,从上面的食谱来看,他们的面包店可能不会很成功,但现在这不重要。)
食谱和库存最初都存储在文件中,每行一个键值对,用::
分隔。上面的库存和食谱可能来自如下文本文件:
flour:: 400
sugar:: 300
salt:: 10
chocolate:: 150
flour:: 200
salt:: 2.5
我们的目标是在recipes.py
中编写一些函数,帮助Parth和Peter管理面包店。首先实现如下函数,该函数接收包含食谱或库存列表的文件名,并将其读取为字典:
def read_dict_from_file(filename):
"""
接收包含食谱或库存列表的文件名,并将其读取为字典。
使用上述文件的示例:
>>> read_dict_from_file('recipe.txt')
{'flour': 200.0, 'salt': 2.5}
"""
注意:所有重量都已转换为float类型。
一旦你建立了构建食谱和库存列表字典的基础设施,请实现以下函数:
def can_make(recipe, pantry):
"""
给定库存内容,返回一个布尔值,指示是否可能按照食谱制作。
注意,此函数的参数是字典,而不是文件名。在此函数中不应修改pantry。
>>> can_make({'flour': 5.0, 'salt': 1.0}, {'flour': 200.0, 'salt': 2.5})
True
>>> can_make({'flour': 5.0, 'salt': 5.0}, {'flour': 200.0, 'salt': 2.5})
False
"""
pass
def make_recipe(recipe, pantry):
"""
给定一个食谱和一个有足够原料制作该食谱的库存,修改库存内容以移除食谱所需的原料数量。
你可以原地修改pantry,但需要返回修改后的pantry以便使用doctest测试输出。
>>> make_recipe({'flour': 5.0, 'salt': 1.0}, {'flour': 200.0, 'salt': 2.5})
{'flour': 195.0, 'salt': 1.5}
"""
pass
我们已经为你实现了主函数的一部分,它首先从用户读取库存文件,然后连续询问用户食谱文件名,如果库存没有足够的原料则打印错误消息,或者如果有足够的每种原料则制作食谱(从库存字典中移除原料),并在之后打印库存。
下面是一个示例运行,反复尝试制作上面的食谱,徒劳地希望有人真的想吃它。注意,你的程序应该能够接受任何有效的食谱或库存文件名。
python3 recipes.py
What pantry file would you like to use? pantry.txt
What recipe would you like to make? recipe.txt
Pantry before:
{'flour': 400.0, 'sugar': 300.0, 'salt': 10.0, 'chocolate': 150.0}
Pantry after:
{'flour': 200.0, 'sugar': 300.0, 'salt': 7.5, 'chocolate': 150.0}
What recipe would you like to make next? recipe.txt
Pantry before:
{'flour': 200.0, 'sugar': 300.0, 'salt': 7.5, 'chocolate': 150.0}
Pantry after:
{'flour': 0.0, 'sugar': 300.0, 'salt': 5.0, 'chocolate': 150.0}
What recipe would you like to make next? recipe.txt
You do not have the ingredients for that recipe!
你可以通过在主函数中输入python3 recipes.py
来运行这个程序(在Windows计算机上使用python或py)。你可以选择上面的pantry.txt,或者稍大一点的full_pantry.txt。我们还包含了几个食谱文件:recipe.txt、pizza_recipe.txt和cookies_recipe.txt。你也可以发挥创意,制作自己的.txt文件!
你会注意到当前打印库存项目的方式不太美观。你的最后一个任务是重新格式化库存项目的打印方式。我们想要的示例运行如下:
python3 recipes.py
What pantry file would you like to use? pantry.txt
What recipe would you like to make? recipe.txt
Pantry before:
flour: 400.0 grams
sugar: 300.0 grams
salt: 10.0 grams
chocolate: 150.0 grams
Pantry after:
flour: 200.0 grams
sugar: 300.0 grams
salt: 7.5 grams
chocolate: 150.0 grams
What recipe would you like to make next? recipe.txt
Pantry before:
flour: 200.0 grams
sugar: 300.0 grams
salt: 7.5 grams
chocolate: 150.0 grams
Pantry after:
flour: 0.0 grams
sugar: 300.0 grams
salt: 5.0 grams
chocolate: 150.0 grams
What recipe would you like to make next? recipe.txt
You do not have the ingredients for that recipe!
f-string是Python中引入的一个特性,允许简单的字符串格式化。要使用f-string,只需在字符串前加上'f',并将你想要包含的表达式或变量用花括号{}
括起来。这些表达式会被求值,它们的值会被插入到字符串中。例如,给定变量name = "Ethan"和age = 21,f-string f"My name is {name}, and I am {age} years old."
将输出"My name is Ethan, and I am 21 years old."。f-string提供了一种简洁且可读的方式来在Python中创建动态字符串,提高了代码的可读性和可维护性。
密码学是研究秘密通信技术的学科。想象一下,Alice和Bob想要互相发送消息,但Eve可以窥探他们发送的消息并读取它们。Alice想要找到一种方法来"加密"她的消息,这样如果Eve读取了消息,她就无法理解它,但Bob将能够"解密"消息。我们要编写一个程序来帮助Alice和Bob做到这一点。
Alice决定将她原始消息中的每个字母替换为另一个字母。为了做到这一点,Alice向ChatGPT(一个能够执行各种任务包括生成JSON字符串的强大语言模型)发出了请求。她请求ChatGPT生成一个表示加密字典的JSON字符串。ChatGPT返回了JSON字符串,Alice将其存储在名为ENCRYPTION_JSON_STRING的变量中:
ENCRYPTION_JSON_STRING = '''
{
"A": "T",
"B": "H",
"C": "E",
"D": "Q",
"E": "U",
"F": "I",
"G": "C",
"H": "K",
...
}
'''
但是,Alice不知道如何将JSON字符串加载到字典中。你需要帮助她完成这部分。为了开始,帮助Alice将JSON字符串ENCRYPTION_JSON_STRING加载到变量ENCRYPTION_DICT中。
Alice和Bob交换了这个ENCRYPTION_DICT字典,所以他们都知道这是策略,但Eve不知道!注意,为了避免歧义,这个字典中的值是唯一的(也就是说,每个字母在字典中恰好作为键和值出现一次)。
请在cryptography.py
中实现以下函数:
def encrypt(plaintext):
"""
接收明文作为输入并返回'密文':用ENCRYPTION_DICT中对应的加密字符替换明文中的每个字母的结果。
明文完全由大写字母和非字母字符(如标点符号)组成。非字母字符不需要加密,但应该以原始形式出现在明文中。
>>> encrypt("HEY, HOW'S IT GOING?")
"KUD, KXZ'S BV CXBFC?"
>>> encrypt("I LOVE CS 106A!")
'B WXLU ES 106T!'
>>> encrypt("UNICORNS ARE THE MOST BEAUTIFUL ANIMALS IN EXISTENCE")
'AFBEXPFS TPU VKU NXSV HUTAVBIAW TFBNTWS BF UYBSVUFEU'
pass
"""
def decrypt(ciphertext):
"""
使用ENCRYPTION_DICT解密密文的每个字母字符。
>>> decrypt("KUD, KXZ'S BV CXBFC?")
"HEY, HOW'S IT GOING?"
>>> decrypt('B WXLU ES 106T!')
'I LOVE CS 106A!'
>>> decrypt('AFBEXPFS TPU VKU NXSV HUTAVBIAW TFBNTWS BF UYBSVUFEU')
'UNICORNS ARE THE MOST BEAUTIFUL ANIMALS IN EXISTENCE'
pass
"""
reverse_encryption_dict
辅助函数。由于每个字母唯一映射,反转时无需考虑一对多。补充:这种加密方式(称为替换密码)其实并不安全。你能发现它的哪些问题?Eve可能如何“破译”密文?