CS61A(Discussion1)

piter 发布于 17 天前 85 次阅读 2375 字


Q1: 赛跑

下面的 race 函数有时会返回错误的值,有时会永远运行。

def race(x, y):
    """The tortoise always walks x feet per minute, while the hare repeatedly
    runs y feet per minute for 5 minutes, then rests for 5 minutes. Return how
    many minutes pass until the tortoise first catches up to the hare.

    >>> race(5, 7)  # After 7 minutes, both have gone 35 steps
    7
    >>> race(2, 4) # After 10 minutes, both have gone 20 steps
    10
    """
    assert y > x and y <= 2 * x, 'the hare must be fast but not too fast'
    tortoise, hare, minutes = 0, 0, 0
    while minutes == 0 or tortoise - hare:
        tortoise += x
        if minutes % 10 < 5:
            hare += y
        minutes += 1
    return minutes

在 61A 代码编辑器里运行 找到满足以下任一条件的正整数 xy(其中 y 大于 x,但不超过 2 * x):

  • race(x, y) 返回错误的值;或
  • race(x, y) 永远运行。

您只需找到一组满足任一条件的数字即可完成此题;当然,您也可以尝试寻找更多组合。

提示:

  • x 被赋值为一个数字时,x += 1x = x + 1 相同。
  • 0 是一个假值,所有其他数字都是真值。

[提示]

当乌龟不是第一次追上兔子时,race(x, y) 的结果才是错误的。尝试一些小于5的较小数字,看看是否能找到这样一种情况:tortoise 已经大于 hare,但此时 tortoise - hare 的值并不为零。

将您找到的 (x, y) 示例发布到小组语音频道中的文本聊天中。如果遇到困难超过十分钟,请及时寻求帮助!

解答:

代码中的循环条件是 while minutes == 0 or tortoise - hare:

  • minutes == 0 确保循环至少执行一次。
  • tortoise - hare 是关键。在 Python 中,任何非零数字都被视为 True (真值),只有 0 被视为 False (假值)。所以,while tortoise - hare: 等价于 while tortoise != hare:

这意味着,循环只有在乌龟和兔子的路程(tortoise 和 hare)完全相等时才会停止

然而,题目要求的是“乌龟第一次追上兔子(the tortoise first catches up to the hare)”的时刻。在现实中,“追上”意味着乌龟的路程大于或等于兔子的路程。代码错误地将这个条件简化为了严格等于

这种偏差会导致两种错误:

  1. 返回错误的值:乌龟可能先是超过了兔子(tortoise > hare),然后由于兔子开始跑,差距又被拉开,直到未来的某个时刻,两者的路程才恰好相等。这时函数返回的是后面这个“恰好相等”的时刻,而不是第一次“追上或超过”的时刻。
  2. 永远运行(死循环):乌龟的路程可能永远无法恰好等于兔子的路程。它可能在某一分钟还落后于兔子,下一分钟就直接超过了兔子,两者路程的差值从一个负数直接跳到一个正数,完美地“跨过”了零。

1. 导致“永远运行”的例子:race(3, 5)

我们来手动跟踪一下 race(3, 5) 的执行过程。

  • x = 3 (乌龟速度)
  • y = 5 (兔子速度)
  • 约束条件检查: 5 > 3 (True) and 5 <= 2 * 3 (True)。满足条件。
Minutes minutes % 10 < 5? Tortoise (乌龟) Hare (兔子) tortoise - hare 说明
初始 0 0 0 循环开始 (minutes == 0)
1 True (跑) 3 5 -2
2 True (跑) 6 10 -4
3 True (跑) 9 15 -6
4 True (跑) 12 20 -8
5 True (跑) 15 25 -10
6 False (歇) 18 25 -7
7 False (歇) 21 25 -4
8 False (歇) 24 25 -1
9 False (歇) 27 25 2 乌龟超过了兔子!但差值不为0,循环继续
10 False (歇) 30 25 5
11 True (跑) 33 30 3 兔子又开始跑了
12 True (跑) 36 35 1
13 True (跑) 39 40 -1 兔子又超过了乌龟

你会发现,在第9分钟,乌龟的路程(27)已经超过了兔子(25),但它们的差值是2,不为0。循环没有停止。之后,它们的差值永远无法回到0。乌龟和兔子的路程差值会不断在正负数之间跳跃,但永远不会恰好是0。

因此,race(3, 5) 会导致一个无限循环。


2. 导致“返回错误值”的例子:race(4, 6)

我们再来跟踪一下 race(4, 6) 的执行过程。

  • x = 4 (乌龟速度)
  • y = 6 (兔子速度)
  • 约束条件检查: 6 > 4 (True) and 6 <= 2 * 4 (True)。满足条件。
Minutes minutes % 10 < 5? Tortoise (乌龟) Hare (兔子) tortoise - hare 说明
... ... ... ... ... (前面几步省略)
7 False (歇) 28 30 -2
8 False (歇) 32 30 2 乌龟第一次追上(并超过)兔子!正确答案应为 8
9 False (歇) 36 30 6 差值不为0,循环继续
10 False (歇) 40 30 10
11 True (跑) 44 36 8
12 True (跑) 48 42 6
13 True (跑) 52 48 4
14 True (跑) 56 54 2
15 True (跑) 60 60 0 路程相等!循环停止,函数返回 15

在这个例子中:

  • 在第8分钟,乌龟的路程(32)第一次超过了兔子(30)。这才是题目意义上的“第一次追上”,所以正确答案应该是 8
  • 但是因为代码检查的是 tortoise == hare,循环没有在第8分钟停止。
  • 直到第15分钟,两者的路程才恰好都为60。此时循环停止,函数返回 15

这是一个错误的值,因为它不是第一次追上的时间。

Q2: Fizzbuzz

实现经典的 Fizz Buzz 序列fizzbuzz 函数接受一个正整数 n,并为 1 到 n 之间的每个整数打印一行输出。 对于每个 i

  • 如果 i 可以同时被 3 和 5 整除,则打印 fizzbuzz
  • 如果 i 可以被 3 整除(但不能被 5 整除),则打印 fizz
  • 如果 i 可以被 5 整除(但不能被 3 整除),则打印 buzz
  • 否则,打印数字 i

尝试使您的 fizzbuzz 实现简洁。

def fizzbuzz(n):
    """
    >>> result = fizzbuzz(16)
    1
    2
    fizz
    4
    buzz
    fizz
    7
    8
    fizz
    buzz
    11
    fizz
    13
    14
    fizzbuzz
    16
    >>> print(result)
    None
    """
    "*** YOUR CODE HERE ***"

Run in 61A Code

[提示]

请注意 ifelif 子句的顺序:首先尝试检查当前数字是否可以同时被 3 和 5 整除,然后检查是否仅能被 3 整除以及是否仅能被 5 整除。

解答:

def fizzbuzz(n):
    """
    >>> result = fizzbuzz(16)
    1
    2
    fizz
    4
    buzz
    fizz
    7
    8
    fizz
    buzz
    11
    fizz
    13
    14
    fizzbuzz
    16
    >>> print(result)
    None
    """
    i = 1
    while i <= n:
        if i % 3 == 0 and i % 5 == 0:
            print("fizzbuzz")
        elif i % 3 == 0:
            print("fizz")
        elif i % 5 == 0:
            print("buzz")
        else:
            print(i)
        i = i + 1
    return None

Q3:是素数吗?

编写一个函数,如果正整数 n 是素数,则返回 True,否则返回 False

素数 n 是一个除了 1 和 n 本身之外不能被任何数字整除的数字。 例如,13 是素数,因为它只能被 1 和 13 整除,但 14 不是,因为它能被 1、2、7 和 14 整除。

使用 % 运算符:x % y 返回 x 除以 y 的余数。

[提示]

以下是一个 while 循环,它会遍历所有大于 1 且小于 n 的整数:

i = 2
while i < n:
    ...
    i = i + 1

可以使用 n % i == 0 来判断 i 是否是 n 的因子。 如果是,则 return False

def is_prime(n):
    """
    >>> is_prime(10)
    False
    >>> is_prime(7)
    True
    >>> is_prime(1) # one is not a prime number!!
    False
    """
    "*** YOUR CODE HERE ***"

在 61A 代码中运行

展示时间:请用一句话概括你们解决 is_prime 问题所使用的思路,确保即使不看代码也能理解。 选出一位同学来讲解,然后在 Discord 的 discuss-queue 频道发送带有 @discuss 标签的消息,内容包括你们的小组编号和 “Prime Time!”。 助教或老师会加入你们的语音频道,听取讲解并给出反馈。

解答:

def is_prime(n):
    """
    >>> is_prime(10)
    False
    >>> is_prime(7)
    True
    >>> is_prime(1) # one is not a prime number!!
    False
    """
    if  n == 1:
        return False
    else:
        i = 2
        while i < n:
            if n % i == 0:
                return False
        i = i + 1
    return True

Q4:唯一数字

编写一个函数,返回正整数中唯一数字的个数。

[提示]

您可以使用 //% 将一个正整数分成它的个位数和其余的数字。

建议先定义一个函数 has_digit(n, k),用来判断数字 n 是否包含数字 k

def unique_digits(n):
    """Return the number of unique digits in positive integer n.

    >>> unique_digits(8675309) # All are unique
    7
    >>> unique_digits(13173131) # 1, 3, and 7
    3
    >>> unique_digits(101) # 0 and 1
    2
    """
    "*** YOUR CODE HERE ***"

def has_digit(n, k):
    """Returns whether k is a digit in n.

    >>> has_digit(10, 1)
    True
    >>> has_digit(12, 7)
    False
    """
    assert k >= 0 and k < 10
    "*** YOUR CODE HERE ***"

在 61A 代码中运行 一种方法是循环遍历从 0 到 9 的每个数字,并检查 n 是否包含该数字。然后数数看总共有多少个不同的数字。

解答:

def unique_digits(n):
    """Return the number of unique digits in positive integer n.

    >>> unique_digits(8675309) # All are unique
    7
    >>> unique_digits(13173131) # 1, 3, and 7
    3
    >>> unique_digits(101) # 0 and 1
    2
    """
    unique = 0
    while n > 0:
        k = n % 10
        n = n // 10
        if not has_digit(n,k):
            unique = unique + 1
    return unique

def has_digit(n, k):
    """Returns whether k is a digit in n.

    >>> has_digit(10, 1)
    True
    >>> has_digit(12, 7)
    False
    """
    assert k >= 0 and k < 10
    while n > 0:
        last = n % 10
        n = n // 10
        if last == k:
            return True
    return False
  • reward_image1
永远不要因为需要大量时间才能完成,就放弃梦想,时间怎么样都会过去的
最后更新于 2025-07-30