作业 2 | CS 61A 2024 年春季学期
作业 2:高阶函数
到期日:2 月 1 日,星期四,晚上 11:59
指示
下载 hw02.zip。在压缩文件中,您会找到一个名为 hw02.py 的文件,以及 ok
自动评分器。
提交: 完成作业后,请将您编辑的所有代码文件上传到 Gradescope 以提交作业。您可以在到期日前多次提交;只有最终提交会被评分。请检查您是否已成功在 Gradescope 上提交了您的代码。有关提交作业的更多指示,请参见 Lab 0。
使用 Ok: 如果您对使用 Ok 有任何疑问,请参阅 此指南。
阅读资源: 您可能会发现以下参考资料很有用:
评分: 作业根据正确性评分。每个不正确的问题将使总分减少一分。此作业满分为 2 分。
题目要求
入门指导视频
这些视频可能会为解决此作业中的编码问题提供一些有用的指导。
要观看这些视频,请使用您的 berkeley.edu 邮箱登录。
一些 doctest 引用了以下函数:
from operator import add, mul
square = lambda x: x * x
identity = lambda x: x
triple = lambda x: 3 * x
increment = lambda x: x + 1
高阶函数
Q1:乘积
请编写一个名为 product
的函数,该函数返回一个序列的前 n
项的乘积。具体来说,product
函数接受一个整数 n
和一个函数 term
作为参数,其中 term
是一个单参数函数,用于确定序列。(也就是说,term(i)
给出序列的第 i
项。)product(n, term)
应该返回 term(1) * ... * term(n)
。
def product(n, term):
"""Return the product of the first n terms in a sequence.
n: a positive integer
term: a function that takes one argument to produce the term
>>> product(3, identity) # 1 * 2 * 3
6
>>> product(5, identity) # 1 * 2 * 3 * 4 * 5
120
>>> product(3, square) # 1^2 * 2^2 * 3^2
36
>>> product(5, square) # 1^2 * 2^2 * 3^2 * 4^2 * 5^2
14400
>>> product(3, increment) # (1+1) * (2+1) * (3+1)
24
>>> product(3, triple) # 1*3 * 2*3 * 3*3
162
"""
"*** YOUR CODE HERE ***"
使用 Ok 测试您的代码:
python3 ok -q product
Q2:累积
接下来,我们来看看 product
函数是如何作为更通用的 accumulate
函数的一个特例:
def accumulate(fuse, start, n, term):
"""Return the result of fusing together the first n terms in a sequence
and start. The terms to be fused are term(1), term(2), ..., term(n).
The function fuse is a two-argument commutative & associative function.
>>> accumulate(add, 0, 5, identity) # 0 + 1 + 2 + 3 + 4 + 5
15
>>> accumulate(add, 11, 5, identity) # 11 + 1 + 2 + 3 + 4 + 5
26
>>> accumulate(add, 11, 0, identity) # 11 (fuse is never used)
11
>>> accumulate(add, 11, 3, square) # 11 + 1^2 + 2^2 + 3^2
25
>>> accumulate(mul, 2, 3, square) # 2 * 1^2 * 2^2 * 3^2
72
>>> # 2 + (1^2 + 1) + (2^2 + 1) + (3^2 + 1)
>>> accumulate(lambda x, y: x + y + 1, 2, 3, square)
19
"""
"*** 请在此处填写你的代码 ***"
accumulate
具有以下参数:
fuse
: 一个接受两个参数的函数,用于指定如何将当前项与之前累积的结果进行合并。start
: 累积的初始值n
: 一个非负整数,表示要合并的项数term
: 一个接受单个参数的函数;term(i)
返回序列中的第i
项。
实现 accumulate
,它使用 fuse
函数将由 term
定义的序列的前 n
项与 start
值合并。
例如,accumulate(add, 11, 3, square)
的结果是
add(11, add(square(1), add(square(2), square(3)))) =
11 + square(1) + square(2) + square(3) =
11 + 1 + 4 + 9 = 25
假设
fuse
满足交换律,即fuse(a, b) == fuse(b, a)
,并且满足结合律,即fuse(fuse(a, b), c) == fuse(a, fuse(b, c))
。
然后,将 summation
(来自讲座)和 product
实现为对 accumulate
的单行调用。
重要提示: summation_using_accumulate
和 product_using_accumulate
都应该用以 return
开头的单行代码实现。
def summation_using_accumulate(n, term):
"""Returns the sum: term(1) + ... + term(n), using accumulate.
>>> summation_using_accumulate(5, square)
55
>>> summation_using_accumulate(5, triple)
45
>>> # This test checks that the body of the function is just a return statement.
>>> import inspect, ast
>>> [type(x).__name__ for x in ast.parse(inspect.getsource(summation_using_accumulate)).body[0].body]
['Expr', 'Return']
"""
return ____
def product_using_accumulate(n, term):
"""Returns the product: term(1) * ... * term(n), using accumulate.
>>> product_using_accumulate(4, square)
576
>>> product_using_accumulate(6, triple)
524880
>>> # This test checks that the body of the function is just a return statement.
>>> import inspect, ast
>>> [type(x).__name__ for x in ast.parse(inspect.getsource(product_using_accumulate)).body[0].body]
['Expr', 'Return']
"""
return ____
使用 Ok 测试你的代码:
python3 ok -q accumulate
python3 ok -q summation_using_accumulate
python3 ok -q product_using_accumulate
Q3: Make Repeater
实现函数 make_repeater
,它接受一个单参数函数 f
和一个正整数 n
作为输入。 该函数返回一个新的单参数函数,对于输入 x
,make_repeater(f, n)(x)
将返回将 f
应用于 x
迭代 n
次的结果,即 f(f(...f(x)...))
。 例如,make_repeater(square, 3)(5)
的结果是将 5 平方三次,得到 390625,等同于 square(square(square(5)))
。
def make_repeater(f, n):
"""Returns the function that computes the nth application of f.
>>> add_three = make_repeater(increment, 3)
>>> add_three(5)
8
>>> make_repeater(triple, 5)(1) # 3 * 3 * 3 * 3 * 3 * 1
243
>>> make_repeater(square, 2)(5) # square(square(5))
625
>>> make_repeater(square, 3)(5) # square(square(square(5)))
390625
"""
"*** YOUR CODE HERE ***"
使用 Ok 测试你的代码:
python3 ok -q make_repeater
在本地检查你的分数
你可以运行以下命令来本地查看此作业的得分情况:
python3 ok --score
这不会提交作业! 当你对得分感到满意时,请将作业提交到 Gradescope 以获取学分。
提交
请将你编辑过的文件上传到 Gradescope 上对应的作业以提交作业。Lab 00 包含详细说明。
此外,所有非大型实验室的学生都需要填写此考勤表。 每周提交此表格,无论你是否参加了实验课,或者因为正当理由错过了实验课。 大型实验室的学生不需要填写考勤表。
考试练习
以下是一些来自过去考试的相关问题供你尝试。 这些是可选的。 无法提交它们。
请注意,2020 年春季、2020 年秋季和 2021 年春季的考试允许学生访问解释器,因此问题格式可能与其他年份不同。 无论如何,以下问题是在不使用解释器的情况下练习的好题目。
- 2019 年秋季 MT1 Q3:You Again [高阶函数]
- 2021 年春季 MT1 Q4:Domain on the Range [高阶函数]
- 2021 年秋季 MT1 Q1b:tik [函数和表达式]