Lab
Q1 WWPD: Lists & Ranges
python3 ok -q lists-wwpd -u --local
>>> list(range(3, 6))
[3,4,5,6,7,8]
>>> range(3, 6)
range(3,6)
>>> range(4)[-1]
3
Q4 WWPD: List Comprehensions
>>> [[1] + s for s in [[4], [5, 6]]]
[[1, 4], [1, 5, 6]]
Q8 Making Onions
HW
Q1 Num Eights
计算 n 中 8 出现的次数。
def num_eights(n):
"""Returns the number of times 8 appears as a digit of n.
>>> num_eights(3)
0
>>> num_eights(8)
1
>>> num_eights(88888888)
8
>>> num_eights(2638)
1
>>> num_eights(86380)
2
>>> num_eights(12345)
0
>>> num_eights(8782089)
3
"""
if n == 0:
return 0
return num_eights(n // 10) + (1 if n % 10 == 8 else 0)
Q2 Digit Distance
递归计算 n 各位差的总和。
def digit_distance(n):
"""Determines the digit distance of n.
>>> digit_distance(3)
0
>>> digit_distance(777) # 0 + 0
0
>>> digit_distance(314) # 2 + 3
5
>>> digit_distance(31415926535) # 2 + 3 + 3 + 4 + ... + 2
32
>>> digit_distance(3464660003) # 1 + 2 + 2 + 2 + ... + 3
16
"""
if n < 10:
return 0
return digit_distance(n // 10) + abs(n % 10 - n // 10 % 10)
Q3 Interleaved Sum
对奇数计算 odd_func(n), 对偶数计算 even_func(n),利用递归计算从 0 到 n 的和。
不能使用%来判断 n 是奇数还是偶数。
def interleaved_sum(n, odd_func, even_func):
"""Compute the sum odd_func(1) + even_func(2) + odd_func(3) + ..., up
to n.
>>> identity = lambda x: x
>>> square = lambda x: x * x
>>> triple = lambda x: x * 3
>>> interleaved_sum(5, identity, square) # 1 + 2*2 + 3 + 4*4 + 5
29
>>> interleaved_sum(5, square, identity) # 1*1 + 2 + 3*3 + 4 + 5*5
41
>>> interleaved_sum(4, triple, square) # 1*3 + 2*2 + 3*3 + 4*4
32
>>> interleaved_sum(4, square, triple) # 1*1 + 2*3 + 3*3 + 4*3
28
"""
def sum_odd(k):
if k > n:
return 0
return sum_odd(k + 2) + odd_func(k)
def sum_even(k):
if k > n:
return 0
return sum_even(k + 2) + even_func(k)
return sum_odd(1) + sum_even(2)
因为不能对 n 进行判断奇数还是偶数,所以我们从 1 开始计算,递归到 n。创建两个 helper function,传入 k,计算 k 到 n 的和。
Q4 Count Dollars
一共有 total 的钱,计算可以有多少种找零方式,面值有 1,5,10,20,50,100。
def count_dollars(total):
"""Return the number of ways to make change.
>>> count_dollars(15) # 15 $1 bills, 10 $1 & 1 $5 bills, ... 1 $5 & 1 $10 bills
6
>>> count_dollars(10) # 10 $1 bills, 5 $1 & 1 $5 bills, 2 $5 bills, 10 $1 bills
4
>>> count_dollars(20) # 20 $1 bills, 15 $1 & $5 bills, ... 1 $20 bill
10
>>> count_dollars(45) # How many ways to make change for 45 dollars?
44
>>> count_dollars(100) # How many ways to make change for 100 dollars?
344
>>> count_dollars(200) # How many ways to make change for 200 dollars?
3274
"""
Q5 Count Dollars Upward
Q6 Towers of Hanoi
汉诺塔问题。解法的基本思想是递归。
假设有 A、B、C 三个塔,A 塔有 N 块盘,目标是把这些盘全部移到 C 塔。那么先把 A 塔顶部的 N−1 块盘移动到 B 塔,再把 A 塔剩下的大盘移到 C,最后把 B 塔的 N−1 块盘移到 C。
def move_stack(n, start, end):
"""Print the moves required to move n disks on the start pole to the end
pole without violating the rules of Towers of Hanoi.
n -- number of disks
start -- a pole position, either 1, 2, or 3
end -- a pole position, either 1, 2, or 3
There are exactly three poles, and start and end must be different. Assume
that the start pole has at least n disks of increasing size, and the end
pole is either empty or has a top disk larger than the top n start disks.
>>> move_stack(1, 1, 3)
Move the top disk from rod 1 to rod 3
>>> move_stack(2, 1, 3)
Move the top disk from rod 1 to rod 2
Move the top disk from rod 1 to rod 3
Move the top disk from rod 2 to rod 3
>>> move_stack(3, 1, 3)
Move the top disk from rod 1 to rod 3
Move the top disk from rod 1 to rod 2
Move the top disk from rod 3 to rod 2
Move the top disk from rod 1 to rod 3
Move the top disk from rod 2 to rod 1
Move the top disk from rod 2 to rod 3
Move the top disk from rod 1 to rod 3
"""
assert 1 <= start <= 3 and 1 <= end <= 3 and start != end, "Bad start/end"
if n == 1:
print_move(start, end)
return
else:
mid = 6 - start - end
move_stack(n - 1, start, mid)
print_move(start, end)
move_stack(n - 1, mid, end)