程序代做CS代考 SQL scheme python cache interpreter CS 61A Structure and Interpretation of Computer Programs

CS 61A Structure and Interpretation of Computer Programs
Fall 2014
INSTRUCTIONS
Final Exam
• You have 3 hours to complete the exam.
• The exam is closed book, closed notes, closed computer, closed calculator, except one hand-written 8.5” ⇥ 11”
crib sheet of your own creation and the 3 ocial 61A midterm study guides attached to the back of this exam. • Mark your answers ON THE EXAM ITSELF. If you are not sure of your answer you may wish to provide a
brief explanation.
Last name
First name
SID
Login
TA & section time
Name of the person to your left
Name of the person to your right
All the work on this exam is my own. (please sign)
For sta↵ use only
Q. 1 Q. 2 Q. 3 Q. 4 Q. 5 Q. 6 Total /14 /16 /12 /12 /18 /8 /80

2
Blank Page

1. (14 points) Representing Scheme Lists
For each row below, write the output displayed by the interactive Python interpreter when the expression is evaluated. Expressions are evaluated in order, and expressions may a↵ect later expressions.
Whenever the interpreter would report an error, write Error. You should include any lines displayed before an error. Reminder: The interactive interpreter displays the repr string of the value of a successfully evaluated expression, unless it is None.
The Pair class from Project 4 is described on your final study guide. Recall that its __str__ method returns a Scheme expression, and its __repr__ method returns a Python expression. The full implementation of Pair and nil appear at the end of the exam as an appendix. Assume that you have started Python 3, loaded Pair and nil from scheme reader.py, then executed the following:
blue = Pair(3, Pair(4, nil))
gold = Pair(Pair(6, 7), Pair(8, 9))
def
def
y =
Expression
Pair(1, nil)
print(Pair(1, nil))
1/0
process(s):
cal = s
while isinstance(cal, Pair):
cal.bear = s
cal = cal.second if cal is s:
return cal else:
return Pair(cal, Pair(s.first, process(s.second)))
display(f, s):
if isinstance(s, Pair):
print(s.first, f(f, s.second)) lambda f: lambda x: f(f, x)
3
Output Expression Output
Pair(1, nil) (1) Error
process(blue.second)
print(print(3), 1/0)
print(process(gold))
print(Pair(2, blue))
gold.second.bear.first
print(gold)
y(display)(gold)

4
2. (16 points) Environments
(a) (8 pt) Fill in the environment diagram that results from executing the code below until the entire program is finished, an error occurs, or all frames are filled. You may not need to use all of the spaces or frames.
A complete answer will:
• Add all missing names and parent annotations to all local frames. • Add all missing values created during execution.
• Show the return value for each local frame.
1 2 3 4 5 6 7 8
func tattoo(heart) [parent=Global]
def tattoo(heart):
def mom():
nonlocal mom
mom = lambda: heart(2) + 1
return 3
return mom() + mom() + 4
tattoo(lambda ink: ink + 0.5)
Global frame
tattoo
f1: ___________ [parent=____________]
Return Value
f2: ___________ [parent=____________]
Return Value
f3: ___________ [parent=____________]
Return Value
f4: ___________ [parent=____________]
Return Value

(b) (6 pt) For the six-line program below, fill in the three environment diagrams that would result after executing each pair of lines in order. You must use box-and-pointer diagrams to represent list values. You do not need to write the word “list” or write index numbers.
Important: All six lines of code are executed in order! Line 3 is executed after line 2 and line 5 after line 4.
5
1 2
12
Global frame meow
cat
3 4
5 6
meow = [1, 2]
cat = [meow, [4, 5]]
cat[0][1] = cat[1][0]
cat[meow[0]][0] = meow
Global frame meow
cat
meow[0] = [cat.pop(0)]
cat.extend(cat[0][1:])
Global frame meow
cat
(c) (2 pt) Circle the value, True or False, of each expression below when evaluated in the environment created by executing all six lines above. If you leave this question blank, you will receive 1 point.
Circle True or False: meow is cat[0]
Circle True or False: meow[0][0] is cat[0][0]

6
3. (12 points) Expression Trees
Your partner has created an interpreter for a language that can add or multiply positive integers. Expressions are represented as instances of the Tree class and must have one of the following three forms:
• (Primitive) A positive integer entry and no branches, representing an integer
• (Combination) The entry ’+’, representing the sum of the values of its branches
• (Combination) The entry ’*’, representing the product of the values of its branches
The Tree class is on the Midterm 2 Study Guide. The sum of no values is 0. The product of no values is 1.
(a) (6 pt) Unfortunately, multiplication in Python is broken on your computer. Implement eval_with_add, which evaluates an expression without using multiplication. You may fill the blanks with names or call expressions, but the only way you are allowed to combine two numbers is using addition.
def eval_with_add(t):
“””Evaluate an expression tree of * and + using only addition.
>>> plus = Tree(’+’, [Tree(2), Tree(3)])
>>> eval_with_add(plus) 5
>>> times = Tree(’*’, [Tree(2), Tree(3)])
>>> eval_with_add(times)
6
>>> deep = Tree(’*’, [Tree(2), plus, times])
>>> eval_with_add(deep) 60
>>> eval_with_add(Tree(’*’)) 1
“””
if t.entry == ’+’:
return sum(________________________________________________________) elif t.entry == ’*’:
total = ___________________________________________________________ for b in t.branches:
total , term = 0, ______________________________________________ for ___________ in ____________________________________________:
total = total + term return total
else:
return t.entry

(b) (6 pt) A TA suggests an alternative representation of an expression, in which the entry is the value of the expression. For combinations, the operator appears in the left-most (index 0) branch as a leaf.
Implement transform, which takes an expression and mutates all combinations so that their entries are values and their first branches are operators. In addition, transform should return the value of its argument. You may use the calc_apply function defined below.
def calc_apply(operator , args): if operator == ’+’:
return sum(args) elif operator == ’*’:
return product(args)
def product(vals): total = 1
for v in vals: total *= v
return total
def transform(t):
“””Transform expression tree t to have value entries and operator leaves.
>>> seven = Tree(’+’, [Tree(’*’, [Tree(2), Tree(3)]), Tree(1)]) >>> transform(seven)
7
>>> seven
Tree(7, [Tree(+), Tree(6, [Tree(*), Tree(2), Tree(3)]), Tree(1)]) “””
if t.branches: args = []
for b in t.branches: args.append(__________________________________________________)
t.branches = _____________________________________________________
t.entry = ________________________________________________________ return _______________________________________________________________
7
Original format: + Alternative: 7 *1+61 23*23

8
4. (12 points) Lazy Sunday
(a) (4 pt) A flat-map operation maps a function over a sequence and flattens the result. Implement the flat_map
method of the FlatMapper class. You may use at most 3 lines of code, indented however you choose. class FlatMapper:
“””A FlatMapper takes a function fn that returns an iterable value. The flat_map method takes an iterable s and returns a generator over all values in the iterables returned by calling fn on each element of s.
>>> stutter = lambda x: [x, x] >>> m = FlatMapper(stutter)
>>> g = m.flat_map((2, 3, 4, 5)) >>> type(g)

>>> list(g)
[2, 2, 3, 3, 4, 4, 5, 5] “””
def __init__(self, fn): self.fn = fn
def flat_map(self, s): ______________________________________________________________________ ______________________________________________________________________ ______________________________________________________________________
(b) (2 pt) Define cycle that returns a Stream repeating the digits 1, 3, 0, 2, and 4. Hint: (3+2)%5 equals 0. def cycle(start=1):
“””Return a stream repeating 1, 3, 0, 2, 4 forever.
>>> first_k(cycle(), 12) # Return the first 12 elements as a list [1, 3, 0, 2, 4, 1, 3, 0, 2, 4, 1, 3]
“””
def compute_rest ():
return ___________________________________________________________
return Stream(_____________________________ , _________________________)

(c) (4 pt) Implement the Scheme procedure directions, which takes a number n and a symbol sym that is bound to a nested list of numbers. It returns a Scheme expression that evaluates to n by repeatedly applying car and cdr to the nested list. Assume that n appears exactly once in the nested list bound to sym.
Hint: The implementation searches for the number n in the nested list s that is bound to sym. The returned expression is built during the search. See the tests at the bottom of the page for usage examples.
(define (directions n sym) (define (search s exp)
; Search an expression s for n and return an expression based on exp. (cond ((number? s) ____________________________________________________)
((null? s) nil)
(else (search-list s exp))))
(define (search -list s exp)
; Search a nested list s for n and return an expression based on exp.
(let ((first __________________________________________________________) (rest __________________________________________________________))
(if (null? first) rest first)))
(search (eval sym) sym))
(define a ’(1 (2 3) ((4)))) (directions 1 ’a)
; expect (car a) (directions 2 ’a)
; expect (car (car (cdr a))) (define b ’((3 4) 5)) (directions 4 ’b)
; expect (car (cdr (car b)))
(d) (2 pt) What expression will (directions 4 ’a) evaluate to?
9

10
5. (18 points) Basis Loaded
notices that any positive integer can be expressed as a sum of powers of 2. Some examples:
11 = 8 + 2 + 1
23 = 16 + 4 + 2 + 1 24 = 16 + 8
45 = 32 + 8 + 4 + 1
2014 = 1024 + 512 + 256 + 128 + 64 + 16 + 8 + 4 + 2
A basis is a linked list of decreasing integers (such as powers of 2) with the property that any positive integer n can be expressed as the sum of elements in the basis, starting with the largest element that is less than or equal to n.
(a) (4 pt) Implement sum_to, which takes a positive integer n and a linked list of decreasing integers basis. It returns a linked list of elements of the basis that sum to n, starting with the largest element of basis that is less than or equal to n. If no such sum exists, raise an ArithmeticError. Each number in basis can only be used once (or not at all). The Link class is described on your Midterm 2 Study Guide.
def sum_to(n, basis):
“””Return elements of linked list basis that sum to n.
>>> twos = Link(32, Link(16, Link(8, Link(4, Link(2, Link(1)))))) >>> sum_to(11, twos)
Link(8, Link(2, Link(1)))
>>> sum_to(23, twos)
Link(16, Link(4, Link(2, Link(1)))) >>> sum_to(24, twos)
Link(16, Link(8))
>>> sum_to(45, twos)
Link(32, Link(8, Link(4, Link(1)))) “””
if _______________________________________________________________________: return Link.empty
elif _____________________________________________________________________: raise ArithmeticError
elif basis.first > n:
return sum_to(n, basis.rest)
else:
return _______________________________________________________________

(b) (6 pt) Cross out as many lines as possible in the implementation of the FibLink class so that all doctests pass. A FibLink is a subclass of Link that contains decreasing Fibonacci numbers. The up_to method returns a FibLink instance whose first element is the largest Fibonacci number that is less than or equal to positive integer n.
class FibLink(Link):
“””Linked list of Fibonacci numbers.
>>> ten = FibLink(2, FibLink(1)).up_to(10) >>> ten
Link(8, Link(5, Link(3, Link(2, Link(1))))) >>> ten.up_to(1)
Link (1)
>>> six, thirteen = ten.up_to(6), ten.up_to(13)
>>> six
Link(5, Link(3, Link(2, Link(1))))
>>> thirteen
Link(13, Link(8, Link(5, Link(3, Link(2, Link(1)))))) “””
successor = self.first + self.rest
@property
def successor ():
def successor(self):
return first + rest.first
return self.first + self.rest.first
def up_to(n):
def up_to(self, n):
while self.first > n:
self = self.rest.first
self = rest
self.first = self.rest.first
if self.first == n: return self
elif self.first > n:
return self.up_to(n) return self.rest.up_to(n)
elif self.successor > n: elif self.first < n: return else: return return return return self FibLink(self.successor(self), self).up_to(n) FibLink(self.successor , self).up_to(n) FibLink(self.successor(self), self.rest).up_to(n) FibLink(self.successor , self.rest).up_to(n) (c) (2 pt) Circle the ⇥ expression below that describes the number of calls made to FibLink.up_to when evaluating FibLink(2, FibLink(1)).up_to(n). The constant is 1+p5 = 1.618... 2 ⇥(1) ⇥(log n) ⇥(n) ⇥(n2) ⇥(n) 11 12 23*23 (d) (2 pt) Alyssa P. Hacker remarks that Fibonacci numbers also form a basis. How many total calls to FibLink.up_to will be made while evaluating all the doctests of the fib_basis function below? Assume that sum_to and FibLink are implemented correctly. Write your answer in the box. def fib_basis (): """Fibonacci basis with caching. >>> r = fib_basis() >>> r(11)
Link(8, Link(3)) >>> r(23)
Link(21, Link(2))
>>> r(24)
Link(21, Link(3))
>>> r(45)
Link(34, Link(8, Link(3))) “””
fibs = FibLink(2, FibLink(1)) def represent(n):
nonlocal fibs
fibs = fibs.up_to(n) return sum_to(n, fibs)
return represent
(e) (4 pt) Implement fib_sums, a function that takes positive integer n and returns the number of ways that n
can be expressed as a sum of unique Fibonacci numbers. Assume that FibLink is implemented correctly. def fib_sums(n):
“””The number of
>>> fib_sums(9) 2
>>> fib_sums (12) 1
ways n can be expressed as a sum of unique Fibonacci numbers. # 8+1, 5+3+1
# 8+3+1
# 13, 8+5, 8+3+2
“””Ways n can be expressed as a sum of elements in fibs.””” if n == 0:
return 1
elif _________________________________________________________________:
return 0
a = __________________________________________________________________
b = __________________________________________________________________
return a + b
return sums(n, FibLink(2, FibLink(1)).up_to(n))
>>> fib_sums(13)
3
“””
def sums(n, fibs):

6. (8 points) Sequels
Assume that the following table of movie ratings has been created.
create table ratings as
select “The Matrix” as title , select “The Matrix Reloaded”, select “The Matrix Revolutions”, select “Toy Story”,
select “Toy Story 2”,
select “Toy Story 3”,
select “Terminator”,
select “Judgment Day”,
select “Rise of the Machines”, 5;
Correct output
Judgment Day Terminator The Matrix Toy Story Toy Story 2 Toy Story 3
9 as rating 7
5
8
8 9 8 9
union union union union union union union union
13
The correct output table for both questions below happens to be the same. It appears above to the right for your reference. Do not hard code your solution to work only with this table! Your implementations should work correctly even if the contents of the ratings table were to change.
(a) (2 pt) Select the titles of all movies that have a rating greater than 7 in alphabetical order.
(b) (6 pt) Select the titles of all movies for which at least 2 other movies have the same rating. The results should appear in alphabetical order. Repeated results are acceptable. You may only use the SQL features introduced in this course.
with
groups(name, score, n) as (
select _____________ , _________________ , ___________ from ratings union
select _____________ , _________________ , ________ from groups , ratings
where ______________________________________________________________ )
select title from ________________________________________________________ where __________________________________________________________________ order by _______________________________________________________________;

14
Appendix: Pair and nil Implementations
This page does not contain a question. These classes were originally defined in scheme reader.py.
class Pair:
“””A pair has two instance attributes: first and second. For a Pair to be a well-formed list, second is either a well-formed list or nil. Some methods only apply to well-formed lists.
>>> s = Pair(1, Pair(2, nil)) >>> s
Pair(1, Pair(2, nil))
>>> print(s)
(1 2)
“””
def __init__(self, first, second):
self.first = first self.second = second
def __repr__(self):
return “Pair({0}, {1})”.format(repr(self.first), repr(self.second))
def __str__(self):
s = “(” + str(self.first) second = self.second
while isinstance(second , Pair):
s += ” ” + str(second.first)
second = second.second if second is not nil:
s += ” . ” + str(second) return s + “)”
class nil:
“”” The empty list “””
def __repr__(self): return “nil”
def __str__(self): return “()”
def __len__(self): return 0
def __getitem__(self, k): if k < 0: raise IndexError("negative index into list") raise IndexError("list index out of bounds") def map(self, fn): return self nil = nil() # Assignment hides the nil class; there is only one instance Scratch Paper 15 16 Scratch Paper Scratch Paper 17 18 Scratch Paper CS 61A Midterm 1 Study Guide – Page 1 Import statement Name Value Assignment statement Code (left): Statements and expressions Red arrow points to next line.
 Gray arrow points to the line just executed Binding Frames (right): A name is bound to a value In a frame, there is at most one binding per name 208 mul(add(2, mul(4, 6)), add(3, 5)) mul 26 8 add(2, mul(4, 6)) add(3, 5) add 2 24 mul(4, 6) mul 4 6 add 3 5 Pure Functions -2 abs(number): 2 2, 10 pow(x, y): Non-Pure Functions -2 print(...): display “-2” 1024 None Intrinsic name of function called Formal parameter bound to argument Local frame Return value is
 not a binding! User-defined function Built-in function Defining: Formal parameter >>> def square( x ):
return mul(x, x)
(return statement) Call expression: square(2+2) operand: 2+2
argument: 4
operator: square function: func square(x)
Calling/Applying: 4 square( x ):
Argument Intrinsic name
return mul(x, x) 16 Return value
Compound statement
Clause

:

Suite

:
…


!
2 boolean
 contexts
def abs_value(x):
if x > 0: return x
elif x == 0: return 0
else:
return -x
1 statement, 3 clauses,

3 headers,
3 suites,
2
A name evaluates to
the value bound to
that name in the
earliest frame of
the current 1 environment in which
that name is found.
2
Error
1
•An environment is a sequence of frames
•An environment for a non-nested function (no def within def) consists of one local frame, followed by the global frame
Evaluation rule for call expressions:
1.Evaluate the operator and operand subexpressions. 2.Apply the function that is the value of the operator
subexpression to the arguments that are the values of the operand subexpressions.
Applying user-defined functions:
1.Create a new local frame with the same parent as the function that was applied.
2.Bind the arguments to the function’s formal parameter names in that frame.
3.Execute the body of the function in the environment beginning at that frame.
Execution rule for def statements:
1.Create a new function value with the specified name, formal parameters, and function body.
2.Its parent is the first frame of the current environment. 3.Bind the name of the function to the function value in the
first frame of the current environment.
Execution rule for assignment statements:
1.Evaluate the expression(s) on the right of the equal sign. 2.Simultaneously bind the names on the left to those values,
in the first frame of the current environment.
Execution rule for conditional statements:
Each clause is considered in order.
1.Evaluate the header’s expression.
2.If it is a true value, execute the suite, then skip the remaining clauses in the statement.
Evaluation rule for or expressions:
1.Evaluate the subexpression .
2.If the result is a true value v, then the expression
evaluates to v.
3.Otherwise, the expression evaluates to the value of the
subexpression .
Evaluation rule for and expressions:
1.Evaluate the subexpression .
2.If the result is a false value v, then the expression
evaluates to v.
3.Otherwise, the expression evaluates to the value of the
subexpression .
Evaluation rule for not expressions:
1.Evaluate ; The value is True if the result is a false value, and False otherwise.
Execution rule for while statements:
1. Evaluate the header’s expression.
2. If it is a true value, execute the (whole) suite, then return to step 1.
B AB
A call expression and the body of the function being called are evaluated in different environments
1
A
2
1
def fib(n): hof.py
“””Compute the nth Fibonacci number, for N >= 1.”””
pred, curr = 0, 1 # Zeroth and first Fibonacci numbers
k = 1 # curr is the kth Fibonacci number return total
pred, curr = curr, pred + curr
k=k+1
def identity(k):
return curr return k
while k < n: def cube(k): return pow(k, 3) Function of a single argument (not called term) A formal parameter that will be bound to a function def summation(n, term): """Sum the first n terms of a sequence. >>> summation(5, cube)
225
“””
total, k = 0, 1 while k <= n: The cube function is passed as an argument value total, k = total + term(k), k + 1 return total The function bound to term gets called here 0+13 +23 +33 +43 +55 def pi_term(k): return 8 / (k * 4 − 3) / (k * 4 − 1) # Local function definitions; returning functions Def statement Body “y” is not found “y” is not found Return expression Higher-order function: A function that takes a function as an argument value or returns a function as a return value Nested def statements: Functions defined within other function bodies are bound to names in the local frame def make_adder(n): CS 61A Midterm 1 Study Guide – Page 2 square = lambda x,y: x * y Evaluates to a function.
 square = lambda x: x * x VS def square(x): return x * x • Both create a function with the same domain, range, and behavior. • Both functions have as their parent the environment in which they were defined. • Both bind that function to the name square. • Only the def statement gives the function an intrinsic name. When a function is defined: A function No "return" keyword! with formal parameters x and y that returns the value of "x * y" Must be a single expression Can refer to names in the enclosing function A function that returns a function def make_adder(n): """Return a function that takes one argument k and returns k + n. ! The name add_three is bound to a function 1. Create a function value: func () 2. Its parent is the current frame.

>>> add_three = make_adder(3)
>>> add_three(4) 7

“””
def adder(k): return k + n
return adder
A local def statement

3. Bind to the function value in the current frame

(which is the first frame of the current environment).
When a function is called:
1. Add a local frame, titled with the of the function being called.
2. Copy the parent of the function to the local frame: [parent=