Skip to main content

作业 2 | CS 61A 2024 年春季学期

作业 2:高阶函数

到期日:2 月 1 日,星期四,晚上 11:59

指示

下载 hw02.zip。在压缩文件中,您会找到一个名为 hw02.py 的文件,以及 ok 自动评分器。

提交: 完成作业后,请将您编辑的所有代码文件上传到 Gradescope 以提交作业。您可以在到期日前多次提交;只有最终提交会被评分。请检查您是否已成功在 Gradescope 上提交了您的代码。有关提交作业的更多指示,请参见 Lab 0

使用 Ok: 如果您对使用 Ok 有任何疑问,请参阅 此指南

阅读资源: 您可能会发现以下参考资料很有用:

评分: 作业根据正确性评分。每个不正确的问题将使总分减少一分。此作业满分为 2 分。

题目要求

入门指导视频

这些视频可能会为解决此作业中的编码问题提供一些有用的指导。

要观看这些视频,请使用您的 berkeley.edu 邮箱登录。

YouTube 链接

一些 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_accumulateproduct_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 作为输入。 该函数返回一个新的单参数函数,对于输入 xmake_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 年春季的考试允许学生访问解释器,因此问题格式可能与其他年份不同。 无论如何,以下问题是在不使用解释器的情况下练习的好题目。

  1. 2019 年秋季 MT1 Q3:You Again [高阶函数]
  2. 2021 年春季 MT1 Q4:Domain on the Range [高阶函数]
  3. 2021 年秋季 MT1 Q1b:tik [函数和表达式]