[2021 Spring] CS61A 学习笔记 lecture 8 More on functions
lecture 8:More on functions
http://composingprograms.com/pages/33-exceptions.html
汉诺塔
汉诺塔是非常经典的递归问题,几乎所有课程讲到递归都会讲到汉诺塔,就不详细解释了。
递归代码
# Towers of Hanoi
def move_tower(n, start_peg, end_peg):
"""Perform moves that transfer an ordered tower of N>0 disks in the
Towers of Hanoi puzzle from peg START_PEG to peg END_PEG, where
1 <= START_PEG, END_PEG <= 3, and START_PEG != END_PEG. Assumes
the disks to be moved are all smaller than those on the other pegs."""
if n == 1:
move_disk(start_peg, end_peg)
else:
spare_peg = 6 - start_peg - end_peg
move_tower(n - 1, start_peg, spare_peg)
move_disk(start_peg, end_peg)
move_tower(n - 1, spare_peg, end_peg)
演示代码
使用python演示移动过程:
## Extra fancy stuff for showing the moves, setting up, and solving the puzzle.
import time
PAUSE = 1.0
pegs = [0, [], [], []]
def solve_puzzle(n):
"""Show the moves to solve a Towers of Hanoi problem for a tower
of N>0 disks."""
set_up_puzzle(n)
print_puzzle()
time.sleep(PAUSE)
move_tower(n, 1, 3)
def set_up_puzzle(n):
"""Set up Towers of Hanoi puzzle with N disks on peg 1, and
other pegs empty."""
pegs[:] = [n, [ k for k in range(n, 0, -1) ], [], []]
def move_disk(peg0, peg1):
"""Move disk from PEG0 and PEG1, printing the result."""
pegs[peg1].append(pegs[peg0].pop())
print_puzzle()
time.sleep(PAUSE)
def print_puzzle():
"""Print current configuration of puzzle (stored in pegs)."""
n = pegs[0]
for k in range(n, 0, -1):
for j in range(1, 4):
print(" ", end="")
if len(pegs[j]) >= k:
c = pegs[j][k-1]
print(" " + " " * (n - c) + "##" * c + " " * (n - c) + " ", end="")
else:
print(" " * (2 * n + 2), end="")
print()
print("=" * (6*n + 9))
print(" " * (n+2) + "1" + " " * (2 * n + 2) + "2" + " " * (2 * n + 2) + "3")
print()
Exceptions
很多函数的语言注释中都有前提条件,比如以上汉诺塔函数的N>0,初始状态盘子是从大到小叠放等。当传递的参数与前提条件冲突时,我们可以用exception处理。
Raise
通过raise an exception表示出现异常情况时抛出异常。
Try
如果提前预料到exception可能出现,并且有比blowing up更有用的响应,可以用try-except语句处理,不会抛出异常。
Exercise: Removing Digits
练习部分(不使用list)
# Deleting digits (spoiler alert!)
def remove_digit(n, digit):
"""Assuming N>=0, 0 <= DIGIT <= 9, return a number whose
base-10 representation is the same as N, but with all instances of
DIGIT removed. If all digits removed, return 0.
>>> remove_digit(123, 3)
12
>>> remove_digit(1234, 5)
1234
>>> remove_digit(1234, 1)
234
>>> remove_digit(111111, 1)
0
"""
if n == 0:
return 0
if n % 10 == digit:
return remove_digit(n // 10, digit)
return n % 10 + remove_digit(n // 10, digit) * 10