首页 > 技术文章 > [2021 Spring] CS61A 学习笔记 lecture 8 More on functions

ikventure 2021-06-17 16:10 原文

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

推荐阅读