讨论 1:函数、控制流
出勤
你的助教会在讨论期间过来签到。
如果你因正当理由(如生病或时间冲突)错过了讨论课,请在一周内发邮件至 cs61a@berkeley.edu 以获得出勤分。While 和 If
学习使用 if 和 while 是一项基本技能。在本次讨论中,
请专注于我们在前三节课中学习的内容:if、while、
赋值(=)、比较(<、>、==)和算术运算。请不要
使用我们课堂上尚未讨论过的 Python 功能,如 for、
range 和列表。我们将在课程后续有充足的时间来学习这些内容,
现在正是练习使用 if(教材章节
1.5.4)
和 while(教材章节
1.5.5)的时候。
问题求解
实现函数的一个有用方法是:
- 选择一个示例输入和对应的输出。
- 用简单的步骤描述一个过程(用自然语言),从输入计算出输出。
- 确定你需要哪些额外的名称来执行这个过程。
- 使用这些额外的名称用代码实现这个过程。
- 确定你的实现是否真的适用于你最初的示例。
- 确定你的实现是否真的适用于其他示例。(如果不适用,你可能需要修改第2步。)
重要的是,这种方法不是直接从阅读题目到编写代码。
例如,在下一页的 is_prime 问题中,你可以:
- 选择
n为 9 作为输入,False作为输出。 - 过程如下:检查
9(n)不能被 1 到9(n)之间的任何整数整除。 - 引入
i来表示 1 到 9(n)之间的每个数字。 - 实现
is_prime(这部分由你和你的小组来完成)。 - 通过思考代码的执行过程来检查
is_prime(9)是否会返回False。 - 检查
is_prime(3)是否会返回True,is_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,它接受正整数 t 和 n。它返回 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 位。