作業地址: https://inst.eecs.berkeley.edu/~cs61a/sp21/hw/hw04/
目錄
Abstraction
Q1: Weights
參考mobile和arm同一模板
def planet(size):
"""Construct a planet of some size."""
assert size > 0
"*** YOUR CODE HERE ***"
return ['planet', size]
def size(w):
"""Select the size of a planet."""
assert is_planet(w), 'must call size on a planet'
"*** YOUR CODE HERE ***"
return w[1]
Q2: Balanced
要求使用abstraction barrier,禁止使用索引。
考慮平衡性:
- 當m是planet時,本身是平衡的,直接返回True;
- 當m是mobile時,需要計算arm的扭矩torque,torque = arm下的weight*length,左右兩邊的torque相等即表示該mobile是平衡的;
- 另一個要求是每個mobile下的arm都平衡,遞歸即可。
def balanced(m):
"""Return whether m is balanced.
>>> t, u, v = examples()
>>> balanced(t)
True
>>> balanced(v)
True
>>> w = mobile(arm(3, t), arm(2, u))
>>> balanced(w)
False
>>> balanced(mobile(arm(1, v), arm(1, w)))
False
>>> balanced(mobile(arm(1, w), arm(1, v)))
False
>>> from construct_check import check
>>> # checking for abstraction barrier violations by banning indexing
>>> check(HW_SOURCE_FILE, 'balanced', ['Index'])
True
"""
"*** YOUR CODE HERE ***"
if is_planet(m):
return True
return total_weight(end(left(m))) * length(left(m)) == \
total_weight(end(right(m))) * length(right(m)) and \
balanced(end(left(m))) and balanced(end(right(m)))
Q3: Totals
- planet返回葉節點,即tree(total_weight(m))
- mobile返回帶有枝干的樹節點,枝為end(arm)的totals_tree,即tree(total_weight(m), [totals_tree(end(left(m))), totals_tree(end(right(m)))])
def totals_tree(m):
"""Return a tree representing the mobile with its total weight at the root.
>>> t, u, v = examples()
>>> print_tree(totals_tree(t))
3
2
1
>>> print_tree(totals_tree(u))
6
1
5
3
2
>>> print_tree(totals_tree(v))
9
3
2
1
6
1
5
3
2
>>> from construct_check import check
>>> # checking for abstraction barrier violations by banning indexing
>>> check(HW_SOURCE_FILE, 'totals_tree', ['Index'])
True
"""
"*** YOUR CODE HERE ***"
if is_planet(m):
return tree(total_weight(m))
return tree(total_weight(m), [totals_tree(end(left(m))), totals_tree(end(right(m)))])
Trees
Q4: Replace Thor at Leaf
base:節點為葉節點且值為'thor'時替換為thors_replacement
def replace_thor_at_leaf(t, thors_replacement):
"""Returns a new tree where every leaf value equal to "thor" has
been replaced with thors_replacement.
>>> yggdrasil = tree('odin',
... [tree('balder',
... [tree('thor'),
... tree('freya')]),
... tree('frigg',
... [tree('thor')]),
... tree('thor',
... [tree('sif'),
... tree('thor')]),
... tree('thor')])
>>> laerad = copy_tree(yggdrasil) # copy yggdrasil for testing purposes
>>> print_tree(replace_thor_at_leaf(yggdrasil, 'freya'))
odin
balder
freya
freya
frigg
freya
thor
sif
freya
freya
>>> laerad == yggdrasil # Make sure original tree is unmodified
True
"""
"*** YOUR CODE HERE ***"
if is_leaf(t) and label(t) == 'thor':
return tree(thors_replacement)
return tree(label(t), [replace_thor_at_leaf(c, thors_replacement) for c in branches(t)])
Q5: Has Path
- label(t)與word[0]不相等時,返回False
- label(t)與word[0]相等,在len(word)等於1時,完全匹配,返回True
- for循環遍歷branch,傳入word[1:].
def has_path(t, word):
"""Return whether there is a path in a tree where the entries along the path
spell out a particular word.
>>> 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
>>> has_path(greetings, 'hint')
False
"""
assert len(word) > 0, 'no path for empty word.'
"*** YOUR CODE HERE ***"
if label(t) != word[0]:
return False
elif len(word) == 1:
return True
for b in branches(t):
if has_path(b, word[1:]):
return True
return False
Q6: Preorder
前序遍歷:
- 葉節點返回[label(t)]
- 對於每個非葉節點b,將preorder(b)累加到res
- 返回根節點+res
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 ***"
if is_leaf(t):
return [label(t)]
res = []
for b in branches(t):
res += preorder(b)
return [label(t)] + res