提示:本文内容来源于UCB CS61A 2020 Summer课程,详情请点击CS 61A: Structure and Interpretation of Computer Programs
文章目录
前言
本文为2020 Summer UCB CS61a 课程 Diagnostic Quiz 内容
提示:以下是本篇文章正文内容,叙述部分参考题目描述,由本人与chatgpt共同翻译,思路部分及作业部分为作者完成,仅供参考,若有错误欢迎评论指正
Diagnostic Quiz
Key Value Store
Key Value Store 题目描述
A lens store is a store that associates keys with values.
To create a lens store, call the function
lens
, to get aput
function.
This function enables you toput
a key-value pair into the store, and returns two functionsget
and anotherput
.
Theget
function should let you look up a key and return its corresponding value, while the newput
function should let you continue adding on to the existing lens store.Note that you can assume that every key provided is unique. If you try to get the value for a key that does not exist, return 0.
For details, refer to the doctest.
翻译如下
一个
lens
存储器是一个将键与值关联起来的存储器。要创建一个镜头存储器,请调用函数
lens
来获取一个put
函数。
put
函数将键值对放入存储器中,并返回两个函数get
和另一个put
get
函数应该让您查找一个键并返回其对应的值,而新的put
函数应该让您继续添加到现有的lens
存储器中。注意,假设提供的每个键都是唯一的。
若尝试获取不存在的键所对应的值,则返回0。
Key Value Store doctest
"""
>>> put1 = lens()
>>> get2, put2 = put1('cat', 'animal')
>>> get3, put3 = put2('table', 'furniture')
>>> get4, put4 = put3('cup', 'utensil')
>>> get5, put5 = put4('thesis', 'paper')
>>> get5('thesis')
'paper'
>>> get5('cup')
'utensil'
>>> get5('table')
'furniture'
>>> get5('cat')
'animal'
>>> get3('cup')
0
"""
Key Value Store 代码框架
def lens(prev=lambda x: 0):
def put(k, v):
def get(k2):
if _____:
_____
else:
_____
return _____
return _____
Key Value Store 解题思路
根据doctest
我们可以先观察以下返回值
首先是整个lens
函数的返回值,根据
>>> put1 = lens()
操作,我们可以知晓lens
应返回put
函数
def lens(prev=lambda x: 0):
def put(k, v):
def get(k2):
if _____:
_____
else:
_____
return _____
return put
根据以下doctest
和题目描述,我们可以知晓put
函数的返回值应为一个get
函数,一个新的put
函数,而由于get
函数是在put
函数中定义,因此直接返回put, get
肯定只会得到一个NameError,但是根据题目描述中put函数想要返回一个“新”的put
函数,再加上lens
函数的返回值是put,因此我们只返回对lens
函数的递归调用(暂时将其参数空出)
>>> get2, put2 = put1('cat', 'animal')
>>> get3, put3 = put2('table', 'furniture')
>>> get4, put4 = put3('cup', 'utensil')
>>> get5, put5 = put4('thesis', 'paper')
def lens(prev=lambda x: 0):
def put(k, v):
def get(k2):
if _____:
_____
else:
_____
return get, lens(<param: unkown function>)
return put
观察如下doctest
>>> get5('thesis')
'paper'
>>> get5('cup')
'utensil'
>>> get5('table')
'furniture'
>>> get5('cat')
'animal'
>>> get3('cup')
0
我们发现与函数get5
可以获取其put4
及其之前导入的所有键对值,如下我们模拟一下get5('thesis')
所在的环境
def lens(prev=<param: unkown function>):
def put4(k='thesis', v='paper'):
def get5(k2='thesis'):
if _____:
_____
else:
_____
return get, lens(<param: unkown function>)
return put
发现k2
和k
是相等的,因此get5
只需要在当前的lens
中查找即可
即
def put4(k='thesis', v='paper'):
def get5(k2='thesis'):
if k2 == k:
return v
else:
_____
return get, lens(<param: unkown function>)
如果在当前lens
中k2
和k
不等
>>> get5('cup')
'utensil'
>>> get5('table')
'furniture'
>>> get5('cat')
'animal'
那么就需要查找之前put的键值对,因此我们需要在当前lens
中拥有get之前value的接口
再结合给出的代码框架def lens(prev=lambda x: 0):
中,lens
函数的参数prev
是一个隐藏的提示,我们可以通过这个参数在前一个lens
中查找想要的key
所对应的value
值,如下
def put4(k='thesis', v='paper'):
def get5(k2='thesis'):
if k2 == k:
return v
else:
return prev(k2)
return get5, lens(<param: unkown function>)
为了达到目的,prev可以查询上一个lens
中的内容,因此我们put
函数的return语句调用lens
时,应该把当前的get传入lens
的参数当中,如下
def lens(prev=lambda x: 0):
def put(k, v):
def get(k2):
if k2 == k:
return v
else:
return prev(k2)
return get, lens(get)
return put
至于题目中要求没有的键对值返回零,只要查询到第一个创建的lens
,由于k2
和k
仍然不等,所以进入else
语句继续向前查询
但是put1 = lens()
,这个lens
中没有传入任何参数,因此prev
就是default value
,即lambda x: 0
,返回0值,符合题目要求
将doctest
中的代码转换为非递归形式可以方便理解,可能有错误仅供参考
def lens1(prev=lambda x: 0):
def put1(k='cat', v='animal'):
def get2(k2):
if k2 == k:
return v
else:
return prev(k2)
return get2, lens2(get2)
return put1
def lens2(prev=get2):
def put2(k='table', v='furniture'):
def get3(k2):
if k2 == k:
return v
else:
return prev(k2)
return get3, lens3(get3)
return put2
def lens3(prev=get3):
def put3(k='cup', v='utensil'):
def get4(k2):
if k2 == k:
return v
else:
return prev(k2)
return get4, lens4(get4)
return put3
def lens4(prev=get4):
def put4(k='thesis', v='paper'):
def get5(k2):
if k2 == k:
return v
else:
return prev(k2)
return get5, lens5(get5)
return put4
测试通过
$ python3 -m doctest key_value_store.py -v
Trying:
put1 = lens()
Expecting nothing
ok
Trying:
get2, put2 = put1('cat', 'animal')
Expecting nothing
ok
Trying:
get3, put3 = put2('table', 'furniture')
Expecting nothing
ok
Trying:
get4, put4 = put3('cup', 'utensil')
Expecting nothing
ok
Trying:
get5, put5 = put4('thesis', 'paper')
Expecting nothing
ok
Trying:
get5('thesis')
Expecting:
'paper'
ok
Trying:
get5('cup')
Expecting:
'utensil'
ok
Trying:
get5('table')
Expecting:
'furniture'
ok
Trying:
get5('cat')
Expecting:
'animal'
ok
Trying:
get3('cup')
Expecting:
0
ok
1 items had no tests:
key_value_store
1 items passed all tests:
10 tests in key_value_store.lens
10 tests in 2 items.
10 passed and 0 failed.
Test passed.
Storeroom
Storeroom 题目描述
Write a function
storeroom
that takes in a positive integer ‘helium’ and two functionsfn_even
andfn_odd
.It applies
fn_even
to all the even digits in the integer and appliesfn_odd
to all the odd digits in the integer.It then returns whether the result of the even values is greater than the result of the odd values.
You can guarantee that the number has at least one even and odd digit.
翻译如下
实现一个函数 storeroom,其参数为:一个正整数
helium
、两个函数fn_even
和fn_odd
它将
fn_even
应用于helium
中的所有偶数数字,将fn_odd
应用于helium
中的所有奇数数字然后,它返回偶数值的结果是否大于奇数值
输入保证该数字至少有一个偶数位和一个奇数位。
Storeroom doctest
"""
>>> storeroom(1234, lambda x,y: x+y, lambda x,y: x*y) # 4 + 2 > 3 * 1
True
>>> storeroom(11111111111112, lambda x,y: x+y, lambda x,y: x*y) # 2 > 1 * 1 * ... * 1
True
>>> storeroom(11111111111112, lambda x,y: x+y, lambda x,y: x+y) # 2 <= 1 + 1 + ... + 1
False
>>> storeroom(12, lambda x,y: x+y, lambda x,y: x*y) # 2 > 1
True
>>> storeroom(12345, lambda x,y: x+y, lambda x,y: x*y) # 4 + 2 <= 1 * 3 * 5
False
>>> storeroom(18383, lambda x,y: x-y, lambda x,y: x-y) # 8 - 8 > 3 - 3 - 1
True
"""
Storeroom 代码框架
def storeroom(helium, fn_even,fn_odd):
evens_defined, odds_defined = False, False
evens, odds = None, None
while _____:
_____ = _____
if _____:
if _____:
_____
_____
else:
_____
else:
if _____:
_____
_____
else:
_____
return evens > odds
Storeroom 解题思路
观察doctest
,发现其给的注释中数为均为从右往左计算,如1234
,偶数数字计算顺序为4 fn_even 2
而忽视2 fn_even 4
依次使用模运算依次取helium
的最后一位即可
第一反应是下面这个实现,但是有变量没用上,还有空没填
def storeroom(helium, fn_even,fn_odd):
evens_defined, odds_defined = False, False
evens, odds = None, None
while helium:
digit, helium = helium % 10, helium // 10
if digit % 2 == 0:
if evens != None:
evens = fn_even(evens, digit)
# _____
else:
evens = digit
else:
if odds != None:
odds = fn_odd(odds, digit)
# _____
else:
odds = digit
return evens > odds
改一下实现就好
def storeroom(helium, fn_even,fn_odd):
evens_defined, odds_defined = False, False
evens, odds = None, None
while helium:
digit, helium = helium % 10, helium // 10
if digit % 2 == 0:
if evens_defined == False:
evens_defined = True
evens = digit
else:
evens = fn_even(evens, digit)
else:
if odds_defined == False:
odds_defined = True
odds = digit
else:
odds = fn_odd(odds, digit)
return evens > odds
测试通过
$ python3 -m doctest storeroom.py -v
Trying:
storeroom(1234, lambda x,y: x+y, lambda x,y: x*y) # 4 + 2 > 3 * 1
Expecting:
True
ok
Trying:
storeroom(11111111111112, lambda x,y: x+y, lambda x,y: x*y) # 2 > 1 * 1 * ... * 1
Expecting:
True
ok
Trying:
storeroom(11111111111112, lambda x,y: x+y, lambda x,y: x+y) # 2 <= 1 + 1 + ... + 1
Expecting:
False
ok
Trying:
storeroom(12, lambda x,y: x+y, lambda x,y: x*y) # 2 > 1
Expecting:
True
ok
Trying:
storeroom(12345, lambda x,y: x+y, lambda x,y: x*y) # 4 + 2 <= 1 * 3 * 5
Expecting:
False
ok
Trying:
storeroom(18383, lambda x,y: x-y, lambda x,y: x-y) # 8 - 8 > 3 - 3 - 1
Expecting:
True
ok
1 items had no tests:
storeroom
1 items passed all tests:
6 tests in storeroom.storeroom
6 tests in 2 items.
6 passed and 0 failed.
Test passed.
Maximum Subnumber
Maximum Subnumber 题目描述
Given a number
ruler
, finds the largest number of lengthk
or fewer, composed of digits fromruler
, in order.
翻译如下
给定一个数字
ruler
,找到由ruler
中的数字组成的长度不超过k
的最大数字,该数字中的各个输赢按照其在ruler
中的出现顺序排列。
Maximum Subnumber doctest
"""
>>> sculptural(1234, 1)
4
>>> sculptural(32749, 2)
79
>>> sculptural(1917, 2)
97
>>> sculptural(32749, 18)
32749
"""
Maximum Subnumber 代码框架
def sculptural(ruler, k):
if ______________________________:
return _______________________________
a = _____________________________
b = _____________________________
return _____________________________
Maximum Subnumber 解题思路
个人思路如下:
- 假设
ruler
的最后一位在要求的结果中- 则要求的数字的个位正好为ruler的最后一位
- 在
ruler // 10
中找到由ruler // 10
中的数字组成的长度不超过k - 1
的最大数字 - 将以上二者拼接起来
- 假设
ruler
的最后一位不在要求的结果中- 抛弃
ruler
最后一位,在剩余ruler // 10
中找到由ruler // 10
中的数字组成的长度不超过k
的最大数字
- 抛弃
- 比较以上两步的结果,其中较大的那一个就是要求的数字
使用递归函数来完成
def sculptural(ruler, k):
if k == 0 or ruler == 0:
return 0
a = sculptural(ruler // 10, k-1) * 10 + ruler % 10
b = sculptural(ruler // 10, k)
return a if a > b else b
递归出口
if k == 0 or ruler == 0:
return 0
其中,k == 0,表示要求的结果数字位数已经够了,直接返回0,回到k = 1
的那一层即可
而 ruler == 0,则表示所有数字已经找过一遍了,但数字位数仍然没有达到要求,由于题目要求结果可以小于给定长度,所以直接返回0即可
以上实现可以通过题目给的几个测试样例
$ python3 -m doctest maximum_subnumber.py -v
Trying:
sculptural(1234, 1)
Expecting:
4
ok
Trying:
sculptural(32749, 2)
Expecting:
79
ok
Trying:
sculptural(1917, 2)
Expecting:
97
ok
Trying:
sculptural(32749, 18)
Expecting:
32749
ok
1 items had no tests:
maximum_subnumber
1 items passed all tests:
4 tests in maximum_subnumber.sculptural
4 tests in 2 items.
4 passed and 0 failed.
Test passed.