CS61A Lab 14
更好的阅读体验
Lab 14 Solutions lab14.zip
Solution Files
This lab has many files. Remember to write in lab14.scm
for the Scheme questions, lab14.lark
for the BNF question, and lab14.py
for all other questions.
Required Questions
Scheme
Q1: Split
Implement split-at
, which takes a list lst
and a non-negative number n
as input and returns a pair new
such that (car new)
is the first n
elements of lst
and (cdr new)
is the remaining elements of lst
. If n
is greater than the length of lst
, (car new)
should be lst
and (cdr new)
should be nil
.
scm> (car (split-at '(2 4 6 8 10) 3))
(2 4 6)
scm> (cdr (split-at '(2 4 6 8 10) 3))
(8 10)
(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))))))
Use Ok to test your code:
python3 ok -q split-at✂️
Scheme Data Abstraction
Q2: Filter Odd Tree
Write a function filter-odd
which takes a tree
data abstraction and returns a new tree
with all even label
s replaced with nil
.
Consider using the
map
procedure to apply a one-argument function to a list.
Below is a Scheme-ified data abstraction of the Tree class we’ve been working with this semester.
; Constructs tree given label and list of branches
(tree label branches); Returns the label of the tree
(label t); Returns the list of branches of the given tree
(branches t)
(define (filter-odd t)(cond((null? t) nil)((odd? (label t)) (tree (label t) (map filter-odd (branches t))))(else (tree nil (map filter-odd (branches t))))))
Use Ok to test your code:
python3 ok -q filter_odd✂️
Programs as Data
Q3: Swap
Implement swap
which takes an expression expr
representing a call to some procedure and returns the same expression with its first two operands swapped if the value of the second operand is greater than the value of the first. Otherwise, it should just return the original expression. For example, (swap '(- 1 (+ 3 5) 7))
should return the expression (- (+ 3 5) 1 7)
since 1
evaluates to 1
, (+ 3 5)
evaluates to 8
, and 8 > 1
. Any operands after the first two should not be evaluated during the execution of the procedure, and they should be left unchanged in the final expression. You may assume that every operand evaluates to a number and that there are always at least two operands in expr
. You may want to consider using a let
expression in addition to the provided procedures to help simplify your code.
(define (cddr s)(cdr (cdr s))
)(define (cadr s)(car (cdr s))
)(define (caddr s)(car (cddr s))
)(define (swap expr)(let ((op (car expr))(first (car (cdr expr)))(second (caddr expr))(rest (cdr (cddr expr))))(if (> (eval second) (eval first))(cons op (cons second (cons first rest)))expr)))
Use Ok to test your code:
python3 ok -q swap✂️
Regex
Q4: Address First Line
Write a regular expression that parses strings and returns whether it contains the first line of a US mailing address.
US mailing addresses typically contain a block number, which is a sequence of 3-5 digits, following by a street name. The street name can consist of multiple words but will always end with a street type abbreviation, which itself is a sequence of 2-5 English letters. The street name can also optionally start with a cardinal direction (“N”, “E”, “W”, “S”). Everything should be properly capitalized.
Proper capitalization means that the first letter of each name is capitalized. It is fine to have things like “WeirdCApitalization” match.
See the doctests for some examples.
def address_oneline(text):"""Finds and returns if there are expressions in text that represent the first lineof a US mailing address.>>> address_oneline("110 Sproul Hall, Berkeley, CA 94720")True>>> address_oneline("What's at 39177 Farwell Dr? Is there a 39177 Nearwell Dr?")True>>> address_oneline("I just landed at 780 N McDonnell Rd, and I need to get to 1880-ish University Avenue. Help!")True>>> address_oneline("123 Le Roy Ave")True>>> address_oneline("110 Unabbreviated Boulevard")False>>> address_oneline("790 lowercase St")False"""block_number = r"\d{3,5}"cardinal_dir = r"(?:[NEWS] )?" # 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 bool(re.search(f"{block_number} {street_name}", text))
Use Ok to test your code:
python3 ok -q address_oneline✂️
BNF
Q5: WWPD: PyCombinator
Consider this attempt at a BNF grammar for Pycombinator, a grammar which supports a subset of Python’s functionality. Specifically, it is able to parse any expression with a Python arithmetic operator. The grammar is specified below:
?start: pycomb_expressionpycomb_expression: func "(" arg ("," arg)* ")"arg: pycomb_expression | NUMBERfunc: FUNCNAMEFUNCNAME: "add" | "mul" | "sub"%ignore " "
%import common.NUMBER
Let’s understand and modify the functionality of this BNF with a few questions.
Use Ok to test your knowledge by choosing the best answer for each of the following “What Would PyCombinator Do” questions:
python3 ok -q wwpd-bnf -u
Submit
Make sure to submit this assignment by running:
python3 ok --submit
Recommended Questions
The following problems are not required for credit on this lab but may help you prepare for the final.
Trees
Q6: Prune Min
Write a function that prunes a Tree
t
mutatively. t
and its branches always have zero or two branches. For the trees with two branches, reduce the number of branches from two to one by keeping the branch that has the smaller label value. Do nothing with trees with zero branches.
Prune the tree in a direction of your choosing (top down or bottom up). The result should be a linear tree.
def prune_min(t):"""Prune the tree mutatively.>>> t1 = Tree(6)>>> prune_min(t1)>>> t1Tree(6)>>> t2 = Tree(6, [Tree(3), Tree(4)])>>> prune_min(t2)>>> t2Tree(6, [Tree(3)])>>> t3 = Tree(6, [Tree(3, [Tree(1), Tree(2)]), Tree(5, [Tree(3), Tree(4)])])>>> prune_min(t3)>>> t3Tree(6, [Tree(3, [Tree(1)])])"""if t.branches == []:returnprune_min(t.branches[0])prune_min(t.branches[1])if (t.branches[0].label > t.branches[1].label):t.branches.pop(0)else:t.branches.pop(1)return # return statement to block alternate from running# Alternate solutionif t.is_leaf():returnremove_ind = int(t.branches[0].label < t.branches[1].label)t.branches.pop(remove_ind)prune_min(t.branches[0])
Use Ok to test your code:
python3 ok -q prune_min✂️
Q7: 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.
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))246810121416>>> print(add_trees(Tree(2), Tree(3, [Tree(4), Tree(5)])))545>>> print(add_trees(Tree(2, [Tree(3)]), Tree(2, [Tree(3), Tree(4)])))464>>> print(add_trees(Tree(2, [Tree(3, [Tree(4), Tree(5)])]), \Tree(2, [Tree(3, [Tree(4)]), Tree(5)])))46855"""if not t1:return t2if not t2:return t1new_label = t1.label + t2.labelt1_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)])
Use Ok to test your code:
python3 ok -q add_trees✂️
Objects
Let’s implement a game called Election. In this game, two players compete to try and earn the most votes. Both players start with 0 votes and 100 popularity.
The two players alternate turns, and the first player starts. Each turn, the current player chooses an action. There are two types of actions:
- The player can debate, and either gain or lose 50 popularity. If the player has popularity
p1
and the other player has popularityp2
, then the probability that the player gains 50 popularity ismax(0.1, p1 / (p1 + p2))
Note that themax
causes the probability to never be lower than 0.1. - The player can give a speech. If the player has popularity
p1
and the other player has popularityp2
, then the player gainsp1 // 10
votes and popularity and the other player losesp2 // 10
popularity.
The game ends when a player reaches 50 votes, or after a total of 10 turns have been played (each player has taken 5 turns). Whoever has more votes at the end of the game is the winner!
Q8: Player
First, let’s implement the Player
class. Fill in the debate
and speech
methods, that take in another Player
other
, and implement the correct behavior as detailed above. Here are two additional things to keep in mind:
- In the
debate
method, you should call the providedrandom
function, which returns a random float between 0 and 1. The player should gain 50 popularity if the random number is smaller than the probability described above, and lose 50 popularity otherwise. - Neither players’ popularity should ever become negative. If this happens, set it equal to 0 instead.
### Phase 1: The Player Class
class Player:""">>> random = make_test_random()>>> p1 = Player('Hill')>>> p2 = Player('Don')>>> p1.popularity100>>> p1.debate(p2) # random() should return 0.0>>> p1.popularity150>>> p2.popularity100>>> p2.votes0>>> p2.speech(p1)>>> p2.votes10>>> p2.popularity110>>> p1.popularity135>>> # Additional correctness tests>>> p1.speech(p2)>>> p1.votes13>>> p1.popularity148>>> p2.votes10>>> p2.popularity99>>> for _ in range(4): # 0.1, 0.2, 0.3, 0.4... p1.debate(p2)>>> p2.debate(p1)>>> p2.popularity49>>> p2.debate(p1)>>> p2.popularity0"""def __init__(self, name):self.name = nameself.votes = 0self.popularity = 100def debate(self, other):prob = max(0.1, self.popularity / (self.popularity + other.popularity))if random() < prob:self.popularity += 50else:self.popularity = max(0, self.popularity - 50)def speech(self, other):self.votes += self.popularity // 10self.popularity += self.popularity // 10other.popularity -= other.popularity // 10def choose(self, other):return self.speech
Use Ok to test your code:
python3 ok -q Player✂️
Q9: Game
Now, implement the Game
class. Fill in the play
method, which should alternate between the two players, starting with p1
, and have each player take one turn at a time. The choose
method in the Player
class returns the method, either debate
or speech
, that should be called to perform the action.
In addition, fill in the winner
method, which should return the player with more votes, or None
if the players are tied.
### Phase 2: The Game Class
class Game:""">>> p1, p2 = Player('Hill'), Player('Don')>>> g = Game(p1, p2)>>> winner = g.play()>>> p1 is winnerTrue>>> # Additional correctness tests>>> winner is g.winner()True>>> g.turn10>>> p1.votes = p2.votes>>> print(g.winner())None"""def __init__(self, player1, player2):self.p1 = player1self.p2 = player2self.turn = 0def play(self):while not self.game_over():if self.turn % 2 == 0:curr, other = self.p1, self.p2else:curr, other = self.p2, self.p1curr.choose(other)(other)self.turn += 1 return self.winner()def game_over(self):return max(self.p1.votes, self.p2.votes) >= 50 or self.turn >= 10def winner(self):if self.p1.votes > self.p2.votes:return self.p1elif self.p2.votes > self.p1.votes:return self.p2else:return None
Use Ok to test your code:
python3 ok -q Game✂️
Q10: New Players
The choose
method in the Player
class is boring, because it always returns the speech
method. Let’s implement two new classes that inherit from Player
, but have more interesting choose
methods.
Implement the choose
method in the AggressivePlayer
class, which returns the debate
method if the player’s popularity is less than or equal to other
’s popularity, and speech
otherwise. Also implement the choose
method in the CautiousPlayer
class, which returns the debate
method if the player’s popularity is 0, and speech
otherwise.
### Phase 3: New Players
class AggressivePlayer(Player):""">>> random = make_test_random()>>> p1, p2 = AggressivePlayer('Don'), Player('Hill')>>> g = Game(p1, p2)>>> winner = g.play()>>> p1 is winnerTrue>>> # Additional correctness tests>>> p1.popularity = p2.popularity>>> p1.choose(p2) == p1.debateTrue>>> p1.popularity += 1>>> p1.choose(p2) == p1.debateFalse>>> p2.choose(p1) == p2.speechTrue"""def choose(self, other):if self.popularity <= other.popularity:return self.debateelse:return self.speech
class CautiousPlayer(Player):""">>> random = make_test_random()>>> p1, p2 = CautiousPlayer('Hill'), AggressivePlayer('Don')>>> p1.popularity = 0>>> p1.choose(p2) == p1.debateTrue>>> p1.popularity = 1>>> p1.choose(p2) == p1.debateFalse>>> # Additional correctness tests>>> p2.choose(p1) == p2.speechTrue"""def choose(self, other):if self.popularity == 0:return self.debateelse:return self.speech
Use Ok to test your code:
python3 ok -q AggressivePlayer
python3 ok -q CautiousPlayer✂️
Lists
Q11: Intersection - Summer 2015 MT1 Q4
Implement intersection(lst_of_lsts)
, which takes a list of lists and returns a list of distinct elements that appear in all the lists in lst_of_lsts
. If no number appears in all of the lists, return the empty list. You may assume that lst_of_lsts
contains at least one list.
def intersection(lst_of_lsts):"""Returns a list of distinct elements that appear in every list inlst_of_lsts.>>> lsts1 = [[1, 2, 3], [1, 3, 5]]>>> intersection(lsts1)[1, 3]>>> lsts2 = [[1, 4, 2, 6], [7, 2, 4], [4, 4]]>>> intersection(lsts2)[4]>>> lsts3 = [[1, 2, 3], [4, 5], [7, 8, 9, 10]]>>> intersection(lsts3) # No number appears in all lists[]>>> lsts4 = [[3, 3], [1, 2, 3, 3], [3, 4, 3, 5]]>>> intersection(lsts4) # Return list of distinct elements[3]"""elements = []for elem in lst_of_lsts[0]:condition = elem not in elementsfor lst in lst_of_lsts[1:]:if elem not in lst:condition = Falseif condition:elements = elements + [elem] return elements
Use Ok to test your code:
python3 ok -q intersection✂️
Q12: Deck of cards
Write a list comprehension that will create a deck of cards, given a list of suits
and a list of ranks
. Each element in the list will be a card, which is represented by a 2-element list of the form [suit, rank]
.
def deck(suits, ranks):"""Creates a deck of cards (a list of 2-element lists) with the givensuits and ranks. Each element in the returned list should be of the form[suit, rank].>>> deck(['S', 'C'], [1, 2, 3])[['S', 1], ['S', 2], ['S', 3], ['C', 1], ['C', 2], ['C', 3]]>>> deck(['S', 'C'], [3, 2, 1])[['S', 3], ['S', 2], ['S', 1], ['C', 3], ['C', 2], ['C', 1]]>>> deck([], [3, 2, 1])[]>>> deck(['S', 'C'], [])[]"""return [[suit, rank] for suit in suitsfor rank in ranks]
Use Ok to test your code:
python3 ok -q deck✂️
Linked Lists
Q13: O!-Pascal - Fall 2017 Final Q4
Pasal’s Triangle is perhaps familiar to you from the diagram below, which shows the first five rows.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rWEm9zW5-1671336495706)(/Users/misaka/Downloads/CodeSpace/blog/source/_posts/assets/Pascal.png)]
Every square is the sum of the two squares above it (as illustrated by the arrows showing here the value 4 comes from), unless it doesn’t have two squares above it, in whih case its value is 1.
Given a linked list that represents a row in Pasal’s triangle, return a linked list that will represent the row below it.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cU4mc9fr-1671336495707)(/Users/misaka/Downloads/CodeSpace/blog/source/_posts/assets/Pascal2.png)]
def pascal_row(s):""">>> a = Link.empty>>> for _ in range(5):... a = pascal_row(a)... print(a)<1><1 1><1 2 1><1 3 3 1><1 4 6 4 1>"""if s is Link.empty:return Link(1)start = Link(1)last, current = start, swhile current.rest is not Link.empty:last.rest = Link(current.first + current.rest.first)last, current = last.rest, current.restlast.rest = Link(1)return start
Use Ok to test your code:
python3 ok -q pascal_row✂️
CS61A Lab 14相关推荐
- CS61A Lab 8
更好的阅读体验 Lab 8: Midterm Review lab08.zip Due by 11:59pm on Wednesday, March 16. Starter Files Downloa ...
- CS61A Lab 10
更好的阅读体验 Lab 10: Scheme lab10.zip Due by 11:59pm on Wednesday, March 30. Starter Files Download lab10 ...
- CS61A Lab 7
更好的阅读体验 Lab 7: Linked Lists, Trees / Tree Mutation lab07.zip What Would Python Display? Q1: WWPD: Li ...
- CS61A Lab 12
更好的阅读体验 Lab 12: Scheme Data Abstraction lab12.zip Due by 11:59pm on Wednesday, April 13. Starter Fil ...
- CS61A Lab 4
更好的阅读体验 Lab 4: Recursion, Tree Recursion lab04.zip What Would Python Do? Q1: Squared Virahanka Fibon ...
- CS61A Lab 6
更好的阅读体验 Lab 6: Object-Oriented Programming lab06.zip What Would Python Do? These questions use inher ...
- CS61A Lab 1
更好的阅读体验 Lab 1: Variables & Functions, Control lab01.zip What Would Python Display? (WWPD) Q1: WW ...
- CS61A Lab 11
更好的阅读体验 Lab 11: Interpreters lab11.zip Due by 11:59pm on Wednesday, April 6. Starter Files Download ...
- CS61A Lab 13
更好的阅读体验 Lab 13 Solutions lab13.zip Solution Files Topics Consult this section if you need a refreshe ...
最新文章
- r语言 断轴 画图_R语言基础画图/绘图/作图
- set Autotrace的使用
- CentOS7下解决ifconfig command not found的办法
- Hourglass网络
- laravel框架连接Oracle,laravel5.8(十四)连接oracle数据库
- 我常用的几个软件的注册码
- 研究生学习生活日记——未来三年的规划
- high sierra php,mac os high sierra下搭建php多版本-php5.2+php5.6-nginx
- 如何修改文件最后一次修改时间?
- vim Windows版本安装教程
- 《读书是一辈子的事》上篇 认识自己
- 嫉妒(译本)--- 作者:弗兰西斯•培根
- AIDL中的in、out、inout的区别
- NaN在js中的意义
- 【腾讯地图API】制作多途经点的线路导航——路线坐标规划
- 计算机软著进行转让的步骤
- Saltstack安装部署及实践
- 十个海量数据处理方法大总结
- iptables的MAC地址过滤
- 寒潮预警又来了!这10个小诀窍帮你提升严冬抵抗力
热门文章
- 全国大学生大数据技能竞赛(Hadoop集群搭建)
- CentOS 7.0.1503
- HTTP的get和post请求方法以及HTTP接口
- iPhone与小米的体验对比(一)
- IEEE期刊投稿流程
- 网管软件有什么?网管软件推荐
- 人脸识别之人眼定位、人脸矫正、人脸尺寸标准化---Mastering OpenCV with Practical Computer Vision Projects
- 就“敏捷软件开发(第二版)”书评答译者
- 给nz-select的nz-option设置样式
- Python pandas 读取csv/txt数据文件 python读取csv/txt文件