2021 fall cs61a lab14
网址 https://inst.eecs.berkeley.edu/~cs61a/fa21/lab/lab14/
目录
problem1:
从上到下,每一次裁剪掉数值大的那个树枝
def prune_min(t):
"""Prune the tree mutatively.
>>> t1 = Tree(6)
>>> prune_min(t1)
>>> t1
Tree(6)
>>> t2 = Tree(6, [Tree(3), Tree(4)])
>>> prune_min(t2)
>>> t2
Tree(6, [Tree(3)])
>>> t3 = Tree(6, [Tree(3, [Tree(1), Tree(2)]), Tree(5, [Tree(3), Tree(4)])])
>>> prune_min(t3)
>>> t3
Tree(6, [Tree(3, [Tree(1)])])
"""
"*** YOUR CODE HERE ***"
if t.is_leaf():
return
# go deeper if it has 1 child
if len(t.branches) == 1:
prune_min(t.branches[0])
left, right = t.branches[0], t.branches[1]
if left.label < right.label:
del t.branches[1] # prune right branch
prune_min(left)
else:
del t.branches[0] # prune left branch
prune_min(right)
problem2:
这个难在要分为两个部分,不能用之前常用的递归,这里用了let先把后面的实现,再在前一部分加一个数字
(define (split-at lst n)
(cond ((= n 0) (cons nil lst))
((null? lst) (cons lst nil))
(else (let ((rec (split-at (cdr lst) (- n 1))))
(cons (cons (car lst) (car rec)) (cdr rec)))))
)
problem3:
(define (compose-all funcs )
(lambda (x)
(if (null? funcs)
x
((compose-all (cdr funcs)) ((car funcs) x))))
)
problem4:
这个主要是理解题目意思,先是一个三到五位的数字,然后是街道名称,一个可以以[NEWS]单个字母开头也可以不用,然后在是一个多字母的名称,最后是一个2到5个字母的缩写,街道名称全部要大写开头
def address_oneline(text):
"""
Finds and returns expressions in text that represent the first line
of a US mailing address.
>>> address_oneline("110 Sproul Hall, Berkeley, CA 94720")
['110 Sproul Hall']
>>> address_oneline("What's at 39177 Farwell Dr? Is there a 39177 Nearwell Dr?")
['39177 Farwell Dr', '39177 Nearwell Dr']
>>> address_oneline("I just landed at 780 N McDonnell Rd, and I need to get to 1880-ish University Avenue. Help!")
['780 N McDonnell Rd']
>>> address_oneline("123 Le Roy Ave")
['123 Le Roy Ave']
>>> address_oneline("110 Unabbreviated Boulevard")
[]
>>> address_oneline("790 lowercase St")
[]
"""
block_number = r'\d{3,5}'
cardinal_dir = r'(?:[NSWE] )?' # whitespace is important!
street = r'(?:[A-Z][A-Za-z]+ )+'
type_abbr = r'[A-Z][a-z]{1,4}\b'
street_name = f"{cardinal_dir}{street}{type_abbr}"
return re.findall(f"{block_number} {street_name}", text)
problem5 and 6:
create table pizzas as
select "Pizzahhh" as name, 12 as open, 15 as close union
select "La Val's" , 11 , 22 union
select "Sliver" , 11 , 20 union
select "Cheeseboard" , 16 , 23 union
select "Emilia's" , 13 , 18;
create table meals as
select "breakfast" as meal, 11 as time union
select "lunch" , 13 union
select "dinner" , 19 union
select "snack" , 22;
-- Pizza places that open before 1pm in alphabetical order
create table opening as
SELECT name
FROM pizzas
WHERE open < 13 ORDER BY name DESC ;
-- Two meals at the same place
create table double as
SELECT a.meal, b.meal, name
FROM meals as a, meals as b, pizzas
where open <= a.time and a.time <= close and
open <= b.time and b.time <= close and
b.time > a.time + 6;
peoblem 7:
class Player:
"""
>>> random = make_test_random()
>>> p1 = Player('Hill')
>>> p2 = Player('Don')
>>> p1.popularity
100
>>> p1.debate(p2) # random() should return 0.0
>>> p1.popularity
150
>>> p2.popularity
100
>>> p2.votes
0
>>> p2.speech(p1)
>>> p2.votes
10
>>> p2.popularity
110
>>> p1.popularity
135
"""
def __init__(self, name):
self.name = name
self.votes = 0
self.popularity = 100
def debate(self, other):
r = random()
if r < max(0.1, (self.popularity / (self.popularity + other.popularity))):
self.popularity += 50
else:
self.popularity -= 50
if self.popularity < 0:
self.popularity = 0
def speech(self, other):
self.votes += self.popularity // 10
self.popularity += self.popularity // 10
other.popularity -= other.popularity // 10
if other.popularity < 0:
other.popularity = 0
def choose(self, other):
return self.speech
problem8:
class Game:
"""
>>> p1, p2 = Player('Hill'), Player('Don')
>>> g = Game(p1, p2)
>>> winner = g.play()
>>> p1 is winner
True
"""
def __init__(self, player1, player2):
self.p1 = player1
self.p2 = player2
self.turn = 0
def play(self):
while not self.game_over:
if self.turn % 2 == 0 :
cur, other = self.p1, self.p2
else:
cur, other = self.p2, self.p1
cur.choose(other)(other)
self.turn += 1
return self.winner
@property
def game_over(self):
return max(self.p1.votes, self.p2.votes) >= 50 or self.turn >= 10
@property
def winner(self):
if self.p1.votes == self.p2.votes:
return None
if self.p1.votes > self.p2.votes :
return self.p1
else:
return self.p2
problem9:
class AggressivePlayer(Player):
"""
>>> random = make_test_random()
>>> p1, p2 = AggressivePlayer('Don'), Player('Hill')
>>> g = Game(p1, p2)
>>> winner = g.play()
>>> p1 is winner
True
"""
def choose(self, other):
if self.popularity <= other.popularity:
return self.debate
else:
return self.speech
class CautiousPlayer(Player):
"""
>>> random = make_test_random()
>>> p1, p2 = CautiousPlayer('Hill'), AggressivePlayer('Don')
>>> p1.popularity = 0
>>> p1.choose(p2) == p1.debate
True
>>> p1.popularity = 1
>>> p1.choose(p2) == p1.debate
False
"""
def choose(self, other):
if self.popularity == 0:
return self.debate
else:
return self.speech
problem10:
先是给出新的label,然后把不一样长的列表完善到一样长,再建立新的树。
def add_trees(t1, t2):
"""
>>> numbers = Tree(1,
... [Tree(2,
... [Tree(3),
... Tree(4)]),
... Tree(5,
... [Tree(6,
... [Tree(7)]),
... Tree(8)])])
>>> print(add_trees(numbers, numbers))
2
4
6
8
10
12
14
16
>>> print(add_trees(Tree(2), Tree(3, [Tree(4), Tree(5)])))
5
4
5
>>> print(add_trees(Tree(2, [Tree(3)]), Tree(2, [Tree(3), Tree(4)])))
4
6
4
>>> print(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 ***"
if not t1:
return t2
if not t2:
return t1
new_label = t1.label + t2.label
t1_branches, t2_branches = list(t1.branches), list(t2.branches)
length_t1, length_t2 = len(t1_branches), len(t2_branches)
if length_t1 < length_t2:
t1_branches += [None for _ in range(length_t1, length_t2)]
elif length_t1 > length_t2:
t2_branches += [None for _ in range(length_t2, length_t1)]
return Tree(new_label,[add_trees(branch1, branch2) for branch1, branch2 in zip(t1_branches, t2_branches)])
problem 11 and 12:
def foldl(link, fn, z):
""" Left fold
>>> lst = Link(3, Link(2, Link(1)))
>>> foldl(lst, sub, 0) # (((0 - 3) - 2) - 1)
-6
>>> foldl(lst, add, 0) # (((0 + 3) + 2) + 1)
6
>>> foldl(lst, mul, 1) # (((1 * 3) * 2) * 1)
6
"""
if link is Link.empty:
return z
z = fn(z, link.first)
link = link.rest
return foldl(link, fn, z)
def foldr(link, fn, z):
""" Right fold
>>> lst = Link(3, Link(2, Link(1)))
>>> foldr(lst, sub, 0) # (3 - (2 - (1 - 0)))
2
>>> foldr(lst, add, 0) # (3 + (2 + (1 + 0)))
6
>>> foldr(lst, mul, 1) # (3 * (2 * (1 * 1)))
6
"""
if link is Link.empty:
return z
z = fn(link.first, foldr(link.rest, fn, z))
return z
problem 13:
def match_url(text):
"""
>>> match_url("https://cs61a.org/resources/#regular-expressions")
True
>>> match_url("https://pythontutor.com/composingprograms.html")
True
>>> match_url("https://pythontutor.com/should/not.match.this")
False
>>> match_url("https://link.com/nor.this/")
False
>>> match_url("http://insecure.net")
True
>>> match_url("htp://domain.org")
False
"""
scheme = r'https?:\/\/'
domain = r'\w[\w.]+\w'
path = r'\/(?:[\w\/]+)(?:\.\w+)?'
anchor = r'#[\w-]+'
return bool(re.match(rf"^(?:{scheme})?{domain}(?:{path})?(?:{anchor})?$", text))