Lab 5: Python Lists, Trees

Q2: Riffle Shuffle

The familiar riffle shuffle of a deck of cards (or in our case, of a sequence of things) results in a new configuration of cards in which the top card is followed by the middle card, then by the second card, then the card after the middle, and so forth. Assuming the deck (sequence) contains an even number of cards, write a list comprehension that produces the shuffled sequence.

Hint: To write this as a single comprehension, you may find the expression k%2, which evaluates to 0 on even numbers and 1 on odd numbers, to be useful. Consider how you can use the 0 or 1 returned by k%2 to alternatively access the beginning and the middle of the list.

分析:

我是直接根据样例二,找出规律对应的表达式,然后直接实现

复制代码
def riffle(deck):
    """Produces a single, perfect riffle shuffle of DECK, consisting of
    DECK[0], DECK[M], DECK[1], DECK[M+1], ... where M is position of the
    second half of the deck.  Assume that len(DECK) is even.
    >>> riffle([3, 4, 5, 6])
    [3, 5, 4, 6]
    >>> riffle(range(20))
    [0, 10, 1, 11, 2, 12, 3, 13, 4, 14, 5, 15, 6, 16, 7, 17, 8, 18, 9, 19]
    """
    "*** YOUR CODE HERE ***"
    #return [] if len(deck)==0 else deck[0:len(deck)//2]+deck[len(deck)-1:len(deck)//2-1:-1] if len(deck)%2==0 else deck[0:len(deck)//2]+deck[len(deck)-1:len(deck)//2-1:-1]
    #return [] if len(deck)==0 else [deck[x] for x in range(0,len(deck)//2)]+[deck[x] for x in range(len(deck)-1,len(deck)//2-1,-1)]
    return [deck[(i%2)*len(deck)//2+i//2]for i in range(len(deck))]

Q4: Sprout leaves

Define a function sprout_leaves that takes in a tree, t, and a list of leaves, leaves. It produces a new tree that is identical to t, but where each old leaf node has new branches, one for each leaf in leaves.

For example, say we have the tree t = tree(1, [tree(2), tree(3, [tree(4)])]):

复制代码
`  1
 / \
2   3
    |
    4`

If we call sprout_leaves(t, [5, 6]), the result is the following tree:

复制代码
`       1
     /   \
    2     3
   / \    |
  5   6   4
         / \
        5   6`
复制代码
def` `sprout_leaves`(t, leaves):
    `"""Sprout new leaves containing the data in leaves at each leaf in
    the original tree t and return the resulting tree.

    >>> t1 = tree(1, [tree(2), tree(3)])
    >>> print_tree(t1)
    1
      2
      3
    >>> new1 = sprout_leaves(t1, [4, 5])
    >>> print_tree(new1)
    1
      2
        4
        5
      3
        4
        5

    >>> t2 = tree(1, [tree(2, [tree(3)])])
    >>> print_tree(t2)
    1
      2
        3
    >>> new2 = sprout_leaves(t2, [6, 1, 2])
    >>> print_tree(new2)
    1
      2
        3
          6
          1
          2
    """`
    `"*** YOUR CODE HERE ***"`
`

Use Ok to test your code:

复制代码
`python3 ok -q sprout_leaves`

Q5: Don't violate the abstraction barrier!

Note: this question has no code-writing component (if you implemented berry_finder and sprout_leaves correctly!)

When writing functions that use an ADT, we should use the constructor(s) and selector(s) whenever possible instead of assuming the ADT's implementation. Relying on a data abstraction's underlying implementation is known as violating the abstraction barrier, and we never want to do this!

It's possible that you passed the doctests for berry_finder and sprout_leaves even if you violated the abstraction barrier. To check whether or not you did so, run the following command:

Use Ok to test your code:

复制代码
`python3 ok -q check_abstraction`

The check_abstraction function exists only for the doctest, which swaps out the implementations of the tree abstraction with something else, runs the tests from the previous two parts, then restores the original abstraction.

The nature of the abstraction barrier guarantees that changing the implementation of an ADT shouldn't affect the functionality of any programs that use that ADT, as long as the constructors and selectors were used properly.

If you passed the Ok tests for the previous questions but not this one, the fix is simple! Just replace any code that violates the abstraction barrier, i.e. creating a tree with a new list object or indexing into a tree, with the appropriate constructor or selector.

Make sure that your functions pass the tests with both the first and the second implementations of the Tree ADT and that you understand why they should work for both before moving on.

复制代码
def sprout_leaves(t, leaves):
    """Sprout new leaves containing the data in leaves at each leaf in
    the original tree t and return the resulting tree.

    >>> t1 = tree(1, [tree(2), tree(3)])
    >>> print_tree(t1)
    1
      2
      3
    >>> new1 = sprout_leaves(t1, [4, 5])
    >>> print_tree(new1)
    1
      2
        4
        5
      3
        4
        5

    >>> t2 = tree(1, [tree(2, [tree(3)])])
    >>> print_tree(t2)
    1
      2
        3
    >>> new2 = sprout_leaves(t2, [6, 1, 2])
    >>> print_tree(new2)
    1
      2
        3
          6
          1
          2
    """
    "*** YOUR CODE HERE ***"

代码一分析:

复制代码
    # 不能过抽象
    # def find_leaves(t):
    #     for branch in branches(t):
    #         sprout_leaves(branch,leaves)
    #     return t
    # def add_leaves(t):
    #     if is_leaf(t):
    #         t += [tree(x) for x in leaves]
    #         return t
    # find_leaves(t)
    # add_leaves(t)
    # return t

代码一(Q5报错)(希望有大佬能指点一下):

复制代码
Traceback (most recent call last):
  File "D:\pycharm\python document\CS61A class homework\lab05\lab05.py", line 97, in sprout_leaves
    find_leaves(t)
  File "D:\pycharm\python document\CS61A class homework\lab05\lab05.py", line 91, in find_leaves
    sprout_leaves(branch,leaves)
  File "D:\pycharm\python document\CS61A class homework\lab05\lab05.py", line 98, in sprout_leaves
    add_leaves(t)
  File "D:\pycharm\python document\CS61A class homework\lab05\lab05.py", line 95, in add_leaves
    t += [tree(x) for x in leaves]
TypeError: unsupported operand type(s) for +=: 'dict' and 'list'

# Error: expected

# but got
#     Traceback (most recent call last):
#       ...
#     TypeError: unsupported operand type(s) for +=: 'dict' and 'list'

---------------------------------------------------------------------
Test summary
    0 test cases passed before encountering first failed test case

Backup... 50.0% complete

代码二分析:

1.首先判断是否为末端叶

是:加上新叶

否(即存在其他的枝条):

遍历其枝条

2.重复之前的工作

复制代码
    #完美代码
    if is_leaf(t):
      return tree(label(t), [tree(x) for x in leaves])
    return tree(label(t), [sprout_leaves(b, leaves) for b in branches(t)])

Q6: Add trees

Define the function add_trees, which takes in two trees and returns a new tree where each corresponding node from the first tree is added with the node from the second tree. If a node at any particular position is present in one tree but not the other, it should be present in the new tree as well.

Hint: You may want to use the built-in zip function to iterate over multiple sequences at once.

Note: If you feel that this one's a lot harder than the previous tree problems, that's totally fine! This is a pretty difficult problem, but you can do it! Talk about it with other students, and come back to it if you need to.

复制代码
def add_trees(t1, t2):
    """
    >>> numbers = tree(1,
    ...                [tree(2,
    ...                      [tree(3),
    ...                       tree(4)]),
    ...                 tree(5,
    ...                      [tree(6,
    ...                            [tree(7)]),
    ...                       tree(8)])])
    >>> print_tree(add_trees(numbers, numbers))
    2
      4
        6
        8
      10
        12
          14
        16
    >>> print_tree(add_trees(tree(2), tree(3, [tree(4), tree(5)])))
    5
      4
      5
    >>> print_tree(add_trees(tree(2, [tree(3)]), tree(2, [tree(3), tree(4)])))
    4
      6
      4
    >>> print_tree(add_trees(tree(2, [tree(3, [tree(4), tree(5)])]), \
    tree(2, [tree(3, [tree(4)]), tree(5)])))
    4
      6
        8
        5
      5
    """
    "*** YOUR CODE HERE ***"

分析:

1. b1,b2为两个添加树的branch

取b为空列表

2.遍历branch元素

i 属于(0- (对于两个branch元素个数 取 最大值))

(1)如果i<len1 and <len2:

(说明两树共有(共有branch的branch也可能有差异),所以继续深层遍历)

b.apppend(add_tree(b1i,b2[i))

( 2 )i>len1 or i >len2 (不共有的branch可以直接添加)

3.最后返回tree(label(b1)+label(b2),b)

(之前添加都是branch,所以b就是所求树的branch)

答案代码:

复制代码
    b1, b2 = branches(t1), branches(t2)
    b = []
    for i in range(max(len(b1), len(b2))):
        if i >= len(b1):
            b.append(b2[i])
        elif i >= len(b2):
            b.append(b1[i])
        else:
            b.append(add_trees(b1[i], b2[i]))
    return tree(label(t1) + label(t2), b)

完整答案代码(最近配了差不多两天的cs106l的配置,还没成功,有人配置成功的,麻烦私聊我,希望您能有时间):

相关推荐
jay神1 小时前
深度学习的优化器应该怎么选?
人工智能·python·深度学习·毕业设计·课程设计
程序喵大人1 小时前
【C++进阶】STL算法与函数对象 - 09 函数对象保存状态并复用规则
开发语言·c++·算法·stl·函数对象
hsjiasb7 小时前
FreeRTOS学习(二十七)——任务栈与栈溢出检测
开发语言·stm32·学习·学习笔记·freertos
丰锋ff8 小时前
3.1 Qt事件之事件处理器
开发语言·qt
多弗朗皮卡丘8 小时前
C语言梦开始的地方7:函数
c语言·开发语言
月华路8 小时前
G1 垃圾回收:脏卡队列、记忆集与并发精化线程机制
java·开发语言
XLYcmy9 小时前
京东 算法实习一面 下+手撕
c++·python·llm·概率论·数据处理·训练·codebert
虎头金猫9 小时前
如何在群晖NAS上通过Docker部署CloudSaver?群晖部署CloudSaver教程|聚合资源搜索并实现远程访问
运维·服务器·网络·python·docker·容器·pandas
从零开始学习人工智能9 小时前
WSL2部署CUDA12+cuDNN9踩坑实录:ONNX Runtime GPU推理环境搭建全流程
python
gugucoding9 小时前
47. 【Java】Java内存模型(JMM)与可见性
java·开发语言