讨论 1:函数、控制流

出勤

你的助教会在讨论期间过来签到。

如果你因正当理由(如生病或时间冲突)错过了讨论课,请在一周内发邮件至 cs61a@berkeley.edu 以获得出勤分。

While 和 If

学习使用 ifwhile 是一项基本技能。在本次讨论中, 请专注于我们在前三节课中学习的内容:ifwhile、 赋值(=)、比较(<>==)和算术运算。请不要 使用我们课堂上尚未讨论过的 Python 功能,如 forrange 和列表。我们将在课程后续有充足的时间来学习这些内容, 现在正是练习使用 if(教材章节 1.5.4) 和 while(教材章节 1.5.5)的时候。

问题求解

实现函数的一个有用方法是:

  1. 选择一个示例输入和对应的输出。
  2. 用简单的步骤描述一个过程(用自然语言),从输入计算出输出。
  3. 确定你需要哪些额外的名称来执行这个过程。
  4. 使用这些额外的名称用代码实现这个过程。
  5. 确定你的实现是否真的适用于你最初的示例。
  6. 确定你的实现是否真的适用于其他示例。(如果不适用,你可能需要修改第2步。)

重要的是,这种方法不是直接从阅读题目到编写代码。

例如,在下一页的 is_prime 问题中,你可以:

  1. 选择 n 为 9 作为输入,False 作为输出。
  2. 过程如下:检查 9n)不能被 1 到 9n)之间的任何整数整除。
  3. 引入 i 来表示 1 到 9(n)之间的每个数字。
  4. 实现 is_prime(这部分由你和你的小组来完成)。
  5. 通过思考代码的执行过程来检查 is_prime(9) 是否会返回 False
  6. 检查 is_prime(3) 是否会返回 Trueis_prime(1) 是否会返回 False

Q1:是否为素数?

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

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

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

你的答案
答案
def is_prime(n):
    """
    >>> is_prime(2)
    True
    >>> is_prime(7)
    True
    >>> is_prime(9)
    False
    >>> is_prime(1) # one is not a prime number!!
    False
    """
    if n == 1:
        return False
    k = 2
    while k < n:
        if n % k == 0:
            return False
        k += 1
    return True




















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
    """
    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 += 1








Q3:有序数字

实现函数 ordered_digits,它接受一个 正整数作为输入,如果其数字从左到右 是非递减顺序的,则返回 True,否则返回 False。例如, 5、11、127、1357 的数字是有序的,但 21 或 1375 的数字不是。

你的答案
答案
def ordered_digits(x):
    """Return True if the (base 10) digits of X>0 are in non-decreasing
    order, and False otherwise.

    >>> ordered_digits(5)
    True
    >>> ordered_digits(11)
    True
    >>> ordered_digits(127)
    True
    >>> ordered_digits(1357)
    True
    >>> ordered_digits(21)
    False
    >>> result = ordered_digits(1375) # Return, don't print
    >>> result
    False
    """
    last = x % 10
    x = x // 10
    while x > 0:
        if last < x % 10:
            return False
        last = x % 10
        x = x // 10
    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
    """
    unique = 0
    while n > 0:
        last = n % 10
        n = n // 10
        if not has_digit(n, last):
            unique += 1
    return unique

# Alternate solution
def unique_digits_alt(n):
    unique = 0
    i = 0
    while i < 10:
        if has_digit(n, i):
            unique += 1
        i += 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





我们提供了两种答案:

  • 在一种答案中,我们查看当前数字,并检查 其余数字是否包含该数字。只有当该数字 在其余部分不存在时,我们才说它是唯一的。我们对每个数字执行此操作。
  • 在另一种答案中,我们循环遍历数字 0-9 并对 每个数字调用 has_digit。如果返回 true,我们就知道整个数字包含该 数字,可以将唯一计数加一。

Q5:重复

定义:正整数 n 是正整数 m重复序列,如果 n 是由 m 的数字重复一次或多次组成的。例如,616161 是 61 的重复序列,但 61616 不是。

实现 repeating,它接受正整数 tn。它返回 n 是否是某个 t 位整数的重复序列。

你的答案
答案
def repeating(t, n):
    """Return whether t digits repeat to form positive integer n.

    >>> repeating(1, 6161)
    False
    >>> repeating(2, 6161)  # repeats 61 (2 digits)
    True
    >>> repeating(3, 6161)
    False
    >>> repeating(4, 6161)  # repeats 6161 (4 digits)
    True
    >>> repeating(5, 6161)  # there are only 4 digits
    False
    """
    if pow(10, t-1) > n:  # make sure n has at least t digits
        return False
    end = n % pow(10, t)
    rest = n
    while rest:
        if rest % pow(10, t) != end:
           return False
        rest = rest // pow(10, t)
    return True
实现此函数所需的迭代过程是检查 rest 的最后 t 位是否与 n 的最后 t 位匹配,然后移除 rest 的最后 t 位。