CS61A学习笔记(作业篇)

为了制止我半途而废,以及散落各处找不到的笔记,决定在这里记录学习笔记和作业遇到的困难等等。

 

Lab 03

Q4: Repeated, repeated

In Homework 2 you encountered the repeated function, which takes arguments f and n and returns a function equivalent to the nth repeated application of f. This time, we want to write repeated recursively. You'll want to use compose1, given below for your convenience:

def compose1(f, g):
    """"Return a function h, such that h(x) = f(g(x))."""
    def h(x):
        return f(g(x))
    return h
def repeated(f, n):
    """Return the function that computes the nth application of func (recursively!).

    >>> add_three = repeated(lambda x: x + 1, 3)
    >>> add_three(5)
    8
    >>> square = lambda x: x ** 2
    >>> repeated(square, 2)(5) # square(square(5))
    625
    >>> repeated(square, 4)(5) # square(square(square(square(5))))
    152587890625
    >>> repeated(square, 0)(5)
    5
    >>> from construct_check import check
    >>> # ban iteration
    >>> check(HW_SOURCE_FILE, 'repeated',
    ...       ['For', 'While'])
    True
    """
    "*** YOUR CODE HERE ***"

没想出来怎么用 compose1,以及终止条件怎么写。看到答案只能喊妙,一题真是一题包含了高阶函数+递归+匿名函数。

    if n == 0:
        return lambda x:x
    else:
        return compose1(f, repeated(f, n - 1))

Q6 Ping-Pong

CS61A学习笔记(作业篇)_第1张图片

def pingpong(n):
    """Return the nth element of the ping-pong sequence.
    The ping-pong sequence counts up starting from 1 and is always either counting up or counting down. At element k, the direction switches if k is a multiple of 8 or contains the digit 8.
    >>> pingpong(8)
    8
    >>> pingpong(10)
    6
    >>> pingpong(15)
    1
    >>> pingpong(21)
    -1
    >>> pingpong(22)
    -2
    >>> pingpong(30)
    -2
    >>> pingpong(68)
    0
    >>> pingpong(69)
    -1
    >>> pingpong(80)
    0
    >>> pingpong(81)
    1
    >>> pingpong(82)
    0
    >>> pingpong(100)
    -6
    >>> from construct_check import check
    >>> # ban assignment statements
    >>> check(HW_SOURCE_FILE, 'pingpong', ['Assign', 'AugAssign'])
    True
    """
    "*** YOUR CODE HERE ***"
    """
    i = 1
    direction = 1
    result = 1
    while i0:
            direction =-direction
        result += direction
        i+=1
    return result
    """
    def helper(i,d,r):
        if i==n:
            return r
        elif i%8==0 or num_eights(i)>0:
            return helper(i+1,-d,r-d)
        else:
            return helper(i+1,d,r+d)
    return helper(1,1,1)

题目不让用赋值语句,经过他的提示想到这种,不过这种方法n一大就直接爆炸了。不知道有没有更好的方法呢?

HW3

Q3

# Q3 Missing Digits
def missing_digits(n):
    """Given a number a that is in sorted, increasing order,
    return the number of missing digits in n. A missing digit is
    a number between the first and last digit of a that is not in n.
    >>> missing_digits(1248) # 3, 5, 6, 7
    4
    >>> missing_digits(1122) # No missing numbers
    0
    >>> missing_digits(123456) # No missing numbers
    0
    >>> missing_digits(3558) # 4, 6, 7
    3
    >>> missing_digits(35578) # 4, 6
    2
    >>> missing_digits(12456) # 3
    1
    >>> missing_digits(16789) # 2, 3, 4, 5
    4
    >>> missing_digits(19) # 2, 3, 4, 5, 6, 7, 8
    7
    >>> missing_digits(4) # No missing numbers between 4 and 4
    0
    >>> from construct_check import check
    >>> # ban while or for loops
    >>> check(HW_SOURCE_FILE, 'missing_digits', ['While', 'For'])
    True
    """
    "*** YOUR CODE HERE ***"
    # def helper(num,max_digit):
    #     if num==0:
    #         return 0
    #     if num%10

Q4 Count change

看他给的hint,去看了recursion那章里的count_partitions才写出来的,通过了这几个例子,不知道有没有错误。这种递归的想法真的太妙了。

# Q4 Count change
import numpy as np
def count_change(total):
    """Return the number of ways to make change for total.

    >>> count_change(7)
    6
    >>> count_change(10)
    14
    >>> count_change(20)
    60
    >>> count_change(100)
    9828
    >>> from construct_check import check
    >>> # ban iteration
    >>> check(HW_SOURCE_FILE, 'count_change', ['While', 'For'])
    True
    """
    "*** YOUR CODE HERE ***"
    def helper(n,m):
        if n==0: return 1
        if n<0: return 0
        if m == 0: return 0
        return helper(n-m,m)+helper(n,m//2)

    a = np.floor(np.log2(total))
    return helper(total,2**a)

count_change(100)

Q5 Towers of Hanoi

在题目给的hint下写出来了,没有hint还真不一定写得出来,这个递归也好妙,以及好久没写甚至忘记了要return。

# Q5: Towers of Hanoi
"""
rules:
Only one disk may be moved at a time.
Each move consists of taking the top (smallest) disk from one of the rods and sliding it onto another rod, on top of the other disks that may already be present on that rod.
No disk may be placed on top of a smaller disk.

"""
def print_move(origin, destination):
    """Print instructions to move a disk."""
    print("Move the top disk from rod", origin, "to rod", destination)

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"
    "*** YOUR CODE HERE ***"
    if n==1: 
        print_move(start,end)
        return
    move_stack(n-1, start, 6-start-end)
    print_move(start, end)
    move_stack(n-1,6-start-end, end)
    return

HW4

Q5: preorder

学到了sum() 也可以用于列表的展开,效果相当于各子列表相加:sum(list, [])

def preorder(t):
    """Return a list of the entries in this tree in the order that they
    would be visited by a preorder traversal (see problem description).

    >>> numbers = tree(1, [tree(2), tree(3, [tree(4), tree(5)]), tree(6, [tree(7)])])
    >>> preorder(numbers)
    [1, 2, 3, 4, 5, 6, 7]
    >>> preorder(tree(2, [tree(4, [tree(6)])]))
    [2, 4, 6]
    """
    "*** YOUR CODE HERE ***"
    return [label(t)]+sum([preorder(b) for b in branches((t))],[])

preorder(tree(2, [tree(4, [tree(6)])]))

Q6 Has Path 

# 字典树
def has_path(t, phrase):
    """Return whether there is a path in a tree where the entries along the path
    spell out a particular phrase.

    >>> greetings = tree('h', [tree('i'),
    ...                        tree('e', [tree('l', [tree('l', [tree('o')])]),
    ...                                   tree('y')])])
    >>> print_tree(greetings)
    h
      i
      e
        l
          l
            o
        y
    >>> has_path(greetings, 'h')
    True
    >>> has_path(greetings, 'i')
    False
    >>> has_path(greetings, 'hi')
    True
    >>> has_path(greetings, 'hello')
    True
    >>> has_path(greetings, 'hey')
    True
    >>> has_path(greetings, 'bye')
    False
    """
    assert len(phrase) > 0, 'no path for empty phrases.'
    "*** YOUR CODE HERE ***"
    if phrase[0]!=label(t):return False
    if len(phrase)==1: return True
    for b in branches(t):
        if phrase[1]== label(b):
            return has_path(b,phrase[1:])
    return False

greetings = tree('h', [tree('i'),
                            tree('e', [tree('l', [tree('l', [tree('o')])]),
                                       tree('y')])])
print_tree(greetings)
has_path(greetings, 'bye')

 学习这个链接里的写法,非常简洁。https://github.com/PKUFlyingPig/CS61A/blob/master/hws/hw04/hw04.py

"*** YOUR CODE HERE ***"
    if len(phrase) == 1:
        return phrase[0] == label(t)
    return label(t) == phrase[0] and any([has_path(b, phrase[1:]) for b in branches(t)])

 

你可能感兴趣的:(学习)