介绍

下载 hw01.zip

提交:完成后,提交python3 ok --submit。您可以在截止日期前提交多次;只有最终提交的作品才会被评分。检查您是否已在okpy.org上成功提交代码。有关提交作业的更多说明,请参阅实验 0

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

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

重要提示: 8 月 30 日星期一的讲座将涉及阅读材料 1.3-1.5部分,其中包含问题 4、5 和 6 所需的知识。

评分:作业根据正确性进行评分。每道错题都会使总分减少一分。教学大纲中规定了家庭作业补救政策。 这个作业满分2分。

必答题

问题1:欢迎表单

请填写课程大纲测验(基于我们在课程大纲中的政策) 以及可选的 欢迎调查

问题2:A 加 B 的绝对值

在下面的函数中填空实现ab的绝对值,不可以调用abs函数。除了两个空格之外,您不得修改任何提供的代码。

def a_plus_abs_b(a, b):
    """Return a+abs(b), but without calling abs.

    >>> a_plus_abs_b(2, 3)
    5
    >>> a_plus_abs_b(2, -3)
    5
    """
    if b < 0:
        f = _____
    else:
        f = _____
    return f(a, b)

使用 Ok 测试您的代码:

python3 ok -q a_plus_abs_b

问题3:三选二

编写一个函数,将三个正数作为参数,并返回两个最小数的平方和。要求函数主体只使用一行代码。

def two_of_three(x, y, z):
    """Return a*a + b*b, where a and b are the two smallest members of the
    positive numbers x, y, and z.

    >>> two_of_three(1, 2, 3)
    5
    >>> two_of_three(5, 3, 1)
    10
    >>> two_of_three(10, 2, 8)
    68
    >>> two_of_three(5, 5, 5)
    50
    """
    return _____

提示:考虑使用maxormin函数:

>>> max(1, 2, 3)
3
>>> min(-1, -2, -3)
-3

使用 Ok 测试您的代码:

python3 ok -q two_of_three

问题4:最大因子

编写一个函数,接收一个大于 1 的整数参数n并返回小于n的最大因子。

def largest_factor(n):
    """Return the largest factor of n that is smaller than n.

    >>> largest_factor(15) # factors are 1, 3, 5
    5
    >>> largest_factor(80) # factors are 1, 2, 4, 5, 8, 10, 16, 20, 40
    40
    >>> largest_factor(13) # factor is 1 since 13 is prime
    1
    """
    "*** YOUR CODE HERE ***"

提示:要检查是否b整除a,则可以使用表达式a % b == 0,这可以理解为,“a除以b的余数为0。”

使用 Ok 测试您的代码:

python3 ok -q largest_factor

问题5:If 函数重构

这里有两个具有相似结构的函数。在两者中,if防止当x为 0 时出现ZeroDivisionError错误。

def invert(x, limit):
    """Return 1/x, but with a limit.

    >>> x = 0.2
    >>> 1/x
    5.0
    >>> invert(x, 100)
    5.0
    >>> invert(x, 2)    # 2 is smaller than 5
    2

    >>> x = 0
    >>> invert(x, 100)  # No error, even though 1/x divides by 0!
    100
    """
    if x != 0:
        return min(1/x, limit)
    else:
        return limit

def change(x, y, limit):
    """Return abs(y - x) as a fraction of x, but with a limit.

    >>> x, y = 2, 5
    >>> abs(y - x) / x
    1.5
    >>> change(x, y, 100)
    1.5
    >>> change(x, y, 1)    # 1 is smaller than 1.5
    1

    >>> x = 0
    >>> change(x, y, 100)  # No error, even though abs(y - x) / x divides by 0!
    100
    """
    if x != 0:
        return min(abs(y - x) / x, limit)
    else:
        return limit

“重构”程序意味着重写它,使其具有相同的行为,但对设计进行一些更改。下面是尝试通过定义一个包含这两个函数公共结构的新函数limited来重构它们以具有简短的单行定义。

def limited(x, z, limit):
    """Logic that is common to invert and change."""
    if x != 0:
        return min(z, limit)
    else:
        return limit

def invert_short(x, limit):
    """Return 1/x, but with a limit.

    >>> x = 0.2
    >>> 1/x
    5.0
    >>> invert_short(x, 100)
    5.0
    >>> invert_short(x, 2)    # 2 is smaller than 5
    2

    >>> x = 0
    >>> invert_short(x, 100)  # No error, even though 1/x divides by 0!
    100
    """
    return limited(x, 1/x, limit)

def change_short(x, y, limit):
    """Return abs(y - x) as a fraction of x, but with a limit.

    >>> x, y = 2, 5
    >>> abs(y - x) / x
    1.5
    >>> change_short(x, y, 100)
    1.5
    >>> change_short(x, y, 1)    # 1 is smaller than 1.5
    1

    >>> x = 0
    >>> change_short(x, y, 100)  # No error, even though abs(y - x) / x divides by 0!
    100
    """
    return limited(x, abs(y - x) / x, limit)

这个重构的代码有问题!试试看invert_short(0, 100)。它导致ZeroDivisionError错误但是invert(0, 100)没有。

你的首要任务是了解行为改变的原因。在invert中,除以x仅在x不为 0 时发生,但在x为 0 时invert_short会发生除以 0 的情况。阅读 If 语句的求值规则调用表达式以了解原因。

你的第二项工作是编辑invert_shortchange_short使它们具有与invertchange相同的行为但仍然只有一行。您还需要编辑limited. 您在invert里不需要使用andorif;需要注意除法发生的位置。

使用 Ok 测试您的代码:

python3 ok -q invert_short
python3 ok -q change_short

问题6:冰雹序列

道格拉斯·霍夫斯塔特 (Douglas Hofstadter) 的普利策奖获奖著作《哥德尔、埃舍尔、巴赫》提出了以下数学难题。

  1. 选择一个正整数n作为开始。
  2. 如果n是偶数,则除以 2。
  3. 如果n是奇数,则乘以 3 并加 1。
  4. 继续这个过程直到n是 1。

该数字n会上下浮动,但最终以 1 结束(至少对于曾经尝试过的所有数字 – 没有人曾证明该序列会终止)。类似地,冰雹在最终降落在地面之前也在大气中上下移动。

n的值组成的序列通常称为冰雹序列。编写一个函数,它接收一个形式参数名为n的参数,打印出从n开始的冰雹序列,并返回序列中的步数:

def hailstone(n):
    """Print the hailstone sequence starting at n and return its
    length.

    >>> a = hailstone(10)
    10
    5
    16
    8
    4
    2
    1
    >>> a
    7
    """
    "*** YOUR CODE HERE ***"

冰雹序列可能会很长!试一试 27. 你能找到的最长的是多少?

使用 Ok 测试您的代码:

python3 ok -q hailstone

对冰雹或冰雹序列感到好奇吗?看看这些文章:

  • 查看这篇文章以了解有关冰雹如何工作的更多信息!
  • 2019 年,在理解冰雹猜想如何适用于大多数的数字方面取得了重大进展

有意思的题

这个问题超出了 61A 的范围。如果你想要一个额外的挑战,你可以尝试一下,但这只是一个没有实际价值的题,不强求也不推荐。几乎所有的学生都会跳过它,这很好。

问题7:自产生程序

编写一个打印自身的单行程序,仅使用 Python 语言的以下特性:

  • 数字常量
  • 赋值语句
  • 可以使用单引号或双引号表示的字符串
  • 算术运算符+, -, *, 和/
  • 内置的print函数
  • 内置的eval函数,将字符串计算为 Python 表达式
  • 内置的repr函数,它返回一个计算其参数的表达式

您可以通过+将两个字符串相加来连接两个字符串,并通过将其乘以一个整数来重复一个字符串。分号可用于分隔同一行上的多个语句。例如,

>>> c='c';print('a');print('b' + c * 2)
a
bcc

提示:探索应用于字符串的单引号、双引号和repr函数之间的关系 。

打印自身的程序称为 Quine。将您的解答放在名为quine的多行字符串中。

使用 Ok 测试您的代码:

python3 ok -q quine_test
最后修改日期: 2021年9月15日

留言

撰写回覆或留言

发布留言必须填写的电子邮件地址不会公开。