2021 fall cs61a lab09
网址 https://inst.eecs.berkeley.edu/~cs61a/fa21/lab/lab09/#topics
- problem1:
- problem2:
- problem3:
- problem4:
- problem5:
- problem6:
- problem7:
- problem8:
- problem9:
- problem10:
- problem11:
- problem12:
problem1:
注意是“return a new list"
def insert_into_all(item, nested_list):
"""Return a new list consisting of all the lists in nested_list,
but with item added to the front of each. You can assume that
nested_list is a list of lists.
>>> nl = [[], [1, 2], [3]]
>>> insert_into_all(0, nl)
[[0], [0, 1, 2], [0, 3]]
"""
"*** YOUR CODE HERE ***"
return [[item] + l for l in nested_list]
类似递归,理解为除了第一个数字其他已经排列好了,这个时候把第一个数字加到后面每个排列好的再加原来的排列就是最终结果
def subseqs(s):
"""Return a nested list (a list of lists) of all subsequences of S.
The subsequences can appear in any order. You can assume S is a list.
>>> seqs = subseqs([1, 2, 3])
>>> sorted(seqs)
[[], [1], [1, 2], [1, 2, 3], [1, 3], [2], [2, 3], [3]]
>>> subseqs([])
[[]]
"""
if not s :
return [[]]
else:
subset = subseqs(s[1:])
return insert_into_all(s[0], subset) + subset
problem2:
用一个help函数记录先前的值,如果当前的是s[0]比他小这个是s[0]就不加入排列中,然后如果大的话就两种情况,一种是加入一种是不加入。
def non_decrease_subseqs(s):
"""Assuming that S is a list, return a nested list of all subsequences
of S (a list of lists) for which the elements of the subsequence
are strictly nondecreasing. The subsequences can appear in any order.
>>> seqs = non_decrease_subseqs([1, 3, 2])
>>> sorted(seqs)
[[], [1], [1, 2], [1, 3], [2], [3]]
>>> non_decrease_subseqs([])
[[]]
>>> seqs2 = non_decrease_subseqs([1, 1, 2])
>>> sorted(seqs2)
[[], [1], [1], [1, 1], [1, 1, 2], [1, 2], [1, 2], [2]]
"""
def subseq_helper(s, prev):
if not s:
return [[]]
elif s[0] < prev:
return subseq_helper(s[1:], prev)
else:
a = subseq_helper(s[1:], s[0])
b = subseq_helper(s[1:], prev)
return insert_into_all(s[0], a) + b
return subseq_helper(s, -float('inf'))
problem3:
有几个叶子就可以加在叶子上加其他二叉树,就是相乘
def num_trees(n):
"""Returns the number of unique full binary trees with exactly n leaves. E.g.,
1 2 3 3 ...
* * * *
/ \ / \ / \
* * * * * *
/ \ / \
* * * *
>>> num_trees(1)
1
>>> num_trees(2)
1
>>> num_trees(3)
2
>>> num_trees(8)
429
"""
"*** YOUR CODE HERE ***"
if n == 1:
return 1
return sum(num_trees(k) * num_trees(n-k) for k in range(1, n))
problem4:
把两个数字先记录下来然后作比较,再选择进行迭代
def merge(incr_a, incr_b):
"""Yield the elements of strictly increasing iterables incr_a and incr_b, removing
repeats. Assume that incr_a and incr_b have no repeats. incr_a or incr_b may or may not
be infinite sequences.
>>> m = merge([0, 2, 4, 6, 8, 10, 12, 14], [0, 3, 6, 9, 12, 15])
>>> type(m)
>>> list(m)
[0, 2, 3, 4, 6, 8, 9, 10, 12, 14, 15]
>>> def big(n):
... k = 0
... while True: yield k; k += n
>>> m = merge(big(2), big(3))
>>> [next(m) for _ in range(11)]
[0, 2, 3, 4, 6, 8, 9, 10, 12, 14, 15]
"""
iter_a, iter_b = iter(incr_a), iter(incr_b)
next_a, next_b = next(iter_a, None), next(iter_b, None)
"*** YOUR CODE HERE ***"
while next_a is not None or next_b is not None:
if next_a is None or (next_b is not None and next_b < next_a):
yield next_b
next_b = next(iter_b, None)
elif next_b is None or (next_a is not None and next_a < next_b):
yield next_a
next_a = next(iter_a, None)
else:
yield next_a
next_a, next_b = next(iter_a, None), next(iter_b, None)
problem5:
这里题目描述是tuples,但是实际看给的例子,好像是列表,而且好像没用到这个interest
class Account:
"""A bank account that allows deposits and withdrawals.
It tracks the current account balance and a transaction
history of deposits and withdrawals.
>>> eric_account = Account('Eric')
>>> eric_account.deposit(1000000) # depositing paycheck for the week
1000000
>>> eric_account.transactions
[('deposit', 1000000)]
>>> eric_account.withdraw(100) # make a withdrawal to buy dinner
999900
>>> eric_account.transactions
[('deposit', 1000000), ('withdraw', 100)]
>>> print(eric_account) #call to __str__
Eric's Balance: $999900
>>> eric_account.deposit(10)
999910
>>> eric_account #call to __repr__
Accountholder: Eric, Deposits: 2, Withdraws: 1
"""
interest = 0.02
def __init__(self, account_holder):
self.balance = 0
self.holder = account_holder
"*** YOUR CODE HERE ***"
self.transactions = []
def deposit(self, amount):
"""Increase the account balance by amount, add the deposit
to the transaction history, and return the new balance.
"""
"*** YOUR CODE HERE ***"
self.balance += amount
self.transactions.append(('deposit', amount))
return self.balance
def withdraw(self, amount):
"""Decrease the account balance by amount, add the withdraw
to the transaction history, and return the new balance.
"""
"*** YOUR CODE HERE ***"
self.transactions.append(('withdraw', amount))
if amount > self.balance:
return 'Insufficient funds'
self.balance -= amount
return self.balance
def __str__(self):
"*** YOUR CODE HERE ***"
return f"{self.holder}'s Balance: ${self.balance}"
def __repr__(self):
"*** YOUR CODE HERE ***"
num_deposits, num_withdraws = 0, 0
for transaction in self.transactions:
if transaction[0] == "withdraw":
num_withdraws += 1
else:
num_deposits += 1
return f'Accountholder: {self.holder}, Deposits: {num_deposits}, Withdraws: {num_withdraws}'
problem6:
def trade(first, second):
"""Exchange the smallest prefixes of first and second that have equal sum.
>>> a = [1, 1, 3, 2, 1, 1, 4]
>>> b = [4, 3, 2, 7]
>>> trade(a, b) # Trades 1+1+3+2=7 for 4+3=7
'Deal!'
>>> a
[4, 3, 1, 1, 4]
>>> b
[1, 1, 3, 2, 2, 7]
>>> c = [3, 3, 2, 4, 1]
>>> trade(b, c)
'No deal!'
>>> b
[1, 1, 3, 2, 2, 7]
>>> c
[3, 3, 2, 4, 1]
>>> trade(a, c)
'Deal!'
>>> a
[3, 3, 2, 1, 4]
>>> b
[1, 1, 3, 2, 2, 7]
>>> c
[4, 3, 1, 4, 1]
>>> d = [1, 1]
>>> e = [2]
>>> trade(d, e)
'Deal!'
>>> d
[2]
>>> e
[1, 1]
"""
m, n = 1, 1
equal_prefix = lambda: sum(first[:m]) == sum(second[:n])
while m <= len(first) and n <= len(second) and not equal_prefix():
if sum(first[:m]) < sum(second[:n]):
m += 1
else:
n += 1
if equal_prefix():
first[:m], second[:n] = second[:n], first[:m]
return 'Deal!'
else:
return 'No deal!'
problem7:
def shuffle(cards):
"""Return a shuffled list that interleaves the two halves of cards.
>>> shuffle(range(6))
[0, 3, 1, 4, 2, 5]
>>> suits = ['H', 'D', 'S', 'C']
>>> cards = [card(n) + suit for n in range(1,14) for suit in suits]
>>> cards[:12]
['AH', 'AD', 'AS', 'AC', '2H', '2D', '2S', '2C', '3H', '3D', '3S', '3C']
>>> cards[26:30]
['7S', '7C', '8H', '8D']
>>> shuffle(cards)[:12]
['AH', '7S', 'AD', '7C', 'AS', '8H', 'AC', '8D', '2H', '8S', '2D', '8C']
>>> shuffle(shuffle(cards))[:12]
['AH', '4D', '7S', '10C', 'AD', '4S', '7C', 'JH', 'AS', '4C', '8H', 'JD']
>>> cards[:12] # Should not be changed
['AH', 'AD', 'AS', 'AC', '2H', '2D', '2S', '2C', '3H', '3D', '3S', '3C']
"""
assert len(cards) % 2 == 0, 'len(cards) must be even'
half = int(len(cards) / 2)
shuffled = []
for i in range(half):
shuffled.append(cards[i])
shuffled.append(cards[i + half])
return shuffled
problem8:
def insert(link, value, index):
"""Insert a value into a Link at the given index.
>>> link = Link(1, Link(2, Link(3)))
>>> print(link)
<1 2 3>
>>> other_link = link
>>> insert(link, 9001, 0)
>>> print(link)
<9001 1 2 3>
>>> link is other_link # Make sure you are using mutation! Don't create a new linked list.
True
>>> insert(link, 100, 2)
>>> print(link)
<9001 1 100 2 3>
>>> insert(link, 4, 5)
Traceback (most recent call last):
...
IndexError: Out of bounds!
"""
"*** YOUR CODE HERE ***"
def func(link, value, index, now):
if link == Link.empty:
raise IndexError('Out of bounds!')
if now == index:
link.first, link.rest = value, Link(link.first, link.rest)
else:
func(link.rest, value, index, now + 1)
return func(link, value, index, 0)
problem9:
def deep_len(lnk):
""" Returns the deep length of a possibly deep linked list.
>>> deep_len(Link(1, Link(2, Link(3))))
3
>>> deep_len(Link(Link(1, Link(2)), Link(3, Link(4))))
4
>>> levels = Link(Link(Link(1, Link(2)), \
Link(3)), Link(Link(4), Link(5)))
>>> print(levels)
<<<1 2> 3> <4> 5>
>>> deep_len(levels)
5
"""
if lnk == Link.empty:
return 0
elif not isinstance(lnk, Link):
return 1
else:
return deep_len(lnk.first) + deep_len(lnk.rest)
problem10:
def make_to_string(front, mid, back, empty_repr):
""" Returns a function that turns linked lists to strings.
>>> kevins_to_string = make_to_string("[", "|-]-->", "", "[]")
>>> jerrys_to_string = make_to_string("(", " . ", ")", "()")
>>> lst = Link(1, Link(2, Link(3, Link(4))))
>>> kevins_to_string(lst)
'[1|-]-->[2|-]-->[3|-]-->[4|-]-->[]'
>>> kevins_to_string(Link.empty)
'[]'
>>> jerrys_to_string(lst)
'(1 . (2 . (3 . (4 . ()))))'
>>> jerrys_to_string(Link.empty)
'()'
"""
def printer(lnk):
if lnk == Link.empty:
return empty_repr
else:
return front + str(lnk.first) + mid + printer(lnk.rest) + back
return printer
problem11:
def long_paths(t, n):
"""Return a list of all paths in t with length at least n.
>>> long_paths(Tree(1), 0)
[[1]]
>>> long_paths(Tree(1), 1)
[]
>>> t = Tree(3, [Tree(4), Tree(4), Tree(5)])
>>> left = Tree(1, [Tree(2), t])
>>> mid = Tree(6, [Tree(7, [Tree(8)]), Tree(9)])
>>> right = Tree(11, [Tree(12, [Tree(13, [Tree(14)])])])
>>> whole = Tree(0, [left, Tree(13), mid, right])
>>> print(whole)
0
1
2
3
4
4
5
13
6
7
8
9
11
12
13
14
>>> for path in long_paths(whole, 2):
... print(path)
...
[0, 1, 2]
[0, 1, 3, 4]
[0, 1, 3, 4]
[0, 1, 3, 5]
[0, 6, 7, 8]
[0, 6, 9]
[0, 11, 12, 13, 14]
>>> for path in long_paths(whole, 3):
... print(path)
...
[0, 1, 3, 4]
[0, 1, 3, 4]
[0, 1, 3, 5]
[0, 6, 7, 8]
[0, 11, 12, 13, 14]
>>> long_paths(whole, 4)
[[0, 11, 12, 13, 14]]
"""
"*** YOUR CODE HERE ***"
if n <= 0 and t.is_leaf():
return [[t.label]]
paths = []
for b in t.branches:
for path in long_paths(b, n - 1):#这一句是在n小于等于零的时候path才会有值,所以可以过滤小于等于n的长度的列表
paths.append([t.label] + path)
return paths