CS计算机代考程序代写 SQL scheme python interpreter CS 61A Structure and Interpretation of Computer Programs

CS 61A Structure and Interpretation of Computer Programs
Spring 2019 Final Solutions

INSTRUCTIONS

� You have 3 hours to complete the exam.

� The exam is closed book, closed notes, closed computer, closed calculator, except three hand-written 8.5″ × 11″
crib sheet of your own creation and the o�cial CS 61A midterm 1, midterm 2, and �nal study guides.

� Mark your answers on the exam itself. We will not grade answers written on scratch paper.

Last name

First name

Student ID number

CalCentral email ( )

TA

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)

POLICIES & CLARIFICATIONS

� If you need to use the restroom, bring your phone and exam to the front of the room.

� You may use built-in Python functions that do not require import, such as min, max, pow, len, abs, sum, next,
iter, list, tuple, map, filter, zip, all, and any.

� You may not use example functions de�ned on your study guides unless a problem clearly states you can.

� For �ll-in-the-blank coding problems, we will only grade work written in the provided blanks. You may only
write one Python statement per blank line, and it must be indented to the level that the blank is indented.

� Unless otherwise speci�ed, you are allowed to reference functions de�ned in previous parts of the same question.

http://berkeley.edu

2

1. (10 points) Iterators are inevitable

For each of the expressions in the table below, write the output displayed by the interactive Python interpreter
when the expression is evaluated. The output may have multiple lines. The �rst row is completed for you.

� If an error occurs, write Error, but include all output displayed before the error.

� To display a function value, write Function.

� To display an iterator/generator value, write Iterator.

� If an expression would take forever to evaluate, write Forever.

The interactive interpreter displays the contents of the repr string of the value of a successfully evaluated
expression, unless it is None.

Assume that you have started python3 and executed the code shown on the left �rst, then you evaluate each
expression on the right in the order shown. Expressions evaluated by the interpreter have a cumulative e�ect.

def love():

yield 1000

yield from [2000, 3000]

x = love()

L = list(x)

def alternate(real, ity):

i1, i2 = iter(real), iter(ity)

try:

while True:

yield next(i1)

yield next(i2)

except StopIteration:

yield ‘inevitable’

thanos = [‘power’, ‘space’, ‘reality’]

tony = [‘mind’, ‘soul’, ‘time’]

i = iter(tony)

next(i)

tony.extend(list(i))

thanos = tony[2::-2]

Expression Output

pow(10, 2) 100

print(print(‘end’, print(‘game’)), x)

game
end None
None Iterator

L
[1000, 2000, 3000]

next(x)
Error

tony

[`mind’, `soul’, `time’,
`soul’, `time’]

list(alternate(thanos[1:], thanos))

[`mind’, `time’, `in-
evitable’]

Name: 3

2. (10 points) Waitlisted

Fill in the environment diagram that results from executing the
code on the right until the entire program is �nished, an error
occurs, or all frames are �lled. 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 or referenced during execu-
tion.

� Show the return value for each local frame.

� Use box-and-pointer diagrams for lists and tuples.

def wait(listed):
expand(schedule)
listed.insert(1, ’61B’)
n = sum([1 for c in listed if c is course])
return lambda: schedule[0][0][n]

def expand(courses):
courses.append(’70’)
courses.extend(course + [course])

course = [’61A’]
schedule = [course, course]
wait(schedule[:])()

1
2
3
4
5
6
7
8
9
10
11
12
13

def wait(listed):
expand(schedule)
listed.insert(1, ’61B’)
n = sum([1 for c in listed if c is course])
return lambda: schedule[0][0][n]

def expand(courses):
courses.append(’70’)
courses.extend(course + [course])

course = [’61A’]
schedule = [course, course]
wait(schedule[:])()

1
2
3
4
5
6
7
8
9
10
11
12
13

Global frame

func expand(courses) [parent = Global]

f3: ___________ [parent=____________]

Return Value

func wait(listed) [parent = Global]

f2: ___________ [parent=____________]

Return Value

f1: ___________ [parent=____________]

Return Value

wait

expand

course

schedule

wait global

listed

n 2

expand global

courses

None

f1

“A”

λ

list
0 1

‘61A’

list
0

2
‘61B’

list
0 1 2 3 4

’70’ ‘61A’

func [parent= f1]λ

4

3. (9 points) I just want to go home!…

(a) (3 pt) A rook is a piece in the game of chess that can move any number of squares vertically or horizontally.
We put a rook somewhere on integer coordinates in the �rst quadrant (0 ≤ x ≤ ∞ , 0 ≤ y ≤ ∞ ) and put a
spell on it so that it can only move toward the origin (i.e., either down or left).

Complete the function paths2D(x, y) to calculate how many di�erent paths there are to get home at (0,
0) given a starting point (x, y). E.g., the rook at (3, 2) could get back to (0, 0) any one of 10 ways, and the
number of paths for each starting square in (0 ≤ x ≤ 3, 0 ≤ y ≤ 2) is shown below.

def paths2D(x, y):

“””

>>> paths2D(3,2)

10

“””

if x == 0 or y == 0:

return 1

else:

return paths2D(x – 1, y) + paths2D(x, y – 1)

(b) (1 pt) Circle the Θ expression that describes the running time of path2D(n, n) as a function of n.

Θ(1) Θ(log n) Θ(n) Θ(n2) Θ(2n) None of these

Name: 5

(c) (5 pt) One of the elements of Abstraction is generalization! Why stop at 2D? That is, why not have a rook
that can only move toward the origin in N-dimensions?

Complete the function pathsND(vector), to return the number of paths home for this rook starting from
vector, a list specifying its position in N-dimensions: [x, y, z, …].

def decrement_at(vector, i):

vector_copy = vector[:]

vector_copy[i] -= 1

return vector_copy

def pathsND(vector):

“””

>>> pathND([3, 2])

10

>>> pathND([3, 1, 2])

60

“””

if sum(vector) == 0:

return 1

else:

return sum([pathsND(decrement_at(vector, i)) for i in range(len(vector)) if vector[i] > 0])

6

4. (10 points) Streams

(a) (6 pt) We provide map-stream2 that calls f on each of the elements of streams s1 and s2. Refer to prefix
de�ned on the Final Study Guide. Fill in the blanks.

(define (map-stream2 f s1 s2) ;; This allows us to call a 2-argument f

(if (or (null? s1) (null? s2)) ;; Now we don’t need add-streams since we can use this!

nil

(cons-stream (f (car s1) (car s2))

(map-stream2 f

(cdr-stream s1)

(cdr-stream s2)))))

scm> (define (spew x) (cons-stream x (spew x)))

spew

scm> (prefix (spew 3) 5)

(3 3 3 3 3)

scm> (define garply (cons-stream 1 (map-stream2 + (spew 1) garply)))

garply

scm> (prefix garply 5)

(1 2 3 4 5)

scm> (define strange (cons-stream nil (map-stream2 cons garply strange)))

strange

scm> (prefix strange 5)

(() (1) (2 1) (3 2 1) (4 3 2 1))

(b) (2 pt) We remind you of the de�nition of map-stream. Generate the stream baz using only calls to
cons-stream, map-stream and/or map-stream2. You may add a lambda in there if needed.

(define (map-stream f s)

(if (null? s)

nil

(cons-stream (f (car s))

(map-stream f (cdr-stream s)))))

scm> (define baz (cons-stream 1 (cons-stream 2 (map-stream (lambda (x) (+ x 1)) baz))))

baz

scm> (prefix baz 10)

(1 2 2 3 3 4 4 5 5 6)

(c) (2 pt) Circle True or False

cons-stream is a special form: True False

cdr-stream is a special form: True False

Name: 7

5. (6 points) Scope!

For each of the following expressions, indicate what a lexically-scoped Scheme will return and what a dynamically-
scoped Scheme will return. If the evaluation results in an error, just write the word error.

(Note: this is the �rst thing you type into the Scheme session)

scm> (define x 10)

x

scm> (define y 5)

y

scm> (define (f x) (* x y))

f

scm> (let ((y 20))

(f 3))

15 in lexical scope, 60 in dynamic scope

scm> (define x 2)

x

scm> (define y 20)

y

scm> (define (foo x)

(lambda (y) (* x y)))

foo

scm> ((foo 3) 5)

15 in lexical scope, 10 in dynamic scope

6. (2 points) Potpourri

What was NOT one of the �risks� mentioned in detail in Lecture 38 on Social Implications / Society?

#Computers and War (e.g., Autonomous weapons)
#Computers and Medicine (e.g., Therac-25)
Computers and Elections (e.g., The 2016 election)
#Computers and Privacy (e.g., Ten Principles of Online Privacy)

What was NOT one of the technologies mentioned in detail in Lecture 37 on Distributed Computing?

#TOR (i.e., The Onion Router)
#Client / Server Architectures (e.g., CS61A’s website)
IoT (i.e., Internet of Things)
#DNS (i.e., The Domain Name System)

8

7. (8 points) TCO!

(a) (6 pt) The count-evens procedure takes a list of integers and returns the number of elements that are
even. Rewrite count-evens as a tail-call optimized procedure by �lling in the blanks below.

(define (count-evens ints)

(cond ((null? ints) 0)

((even? (car ints)) (+ 1 (count-evens (cdr ints))))

(else (count-evens (cdr ints)))))

(define (count-evens-tail ints)

(define (helper ints total)

(cond ((null? ints) total)

((even? (car ints)) (helper (cdr ints) (+ total 1)))

(else (helper (cdr ints) total))))

(helper ints 0))

(b) (1 pt) Circle the Θ expression that describes the running time of count-evens-tail where n is the length
of the input list ints.

Θ(1) Θ(log n) Θ(n) Θ(n2) Θ(2n) None of these

(c) (1 pt) Circle the Θ expression that describes the space complexity of count-evens-tail where n is the
length of the input list ints.

Θ(1) Θ(log n) Θ(n) Θ(n2) Θ(2n) None of these

8. (4 points) Macros

The if special form has been removed from scheme. Implement an if macro using only and/or:

(define-macro (if condition then else)

`(or (and ,condition ,then) (and (not ,condition) ,else))

scm> (if #t 1 (/ 1 0))

1

scm> (if #f 1 (/ 1 0))

Error

Name: 9

9. (10 points) SQL

Given the tables users, sales, and products answer the following questions.

CREATE TABLE users AS

SELECT “Jon” AS name, 0 AS user_id UNION

SELECT “Arya” , 1 UNION

SELECT “Sansa” , 2 UNION

SELECT “Daenerys” , 3 UNION

SELECT “Cersei” , 4;

CREATE TABLE products AS

SELECT 0 AS product_id, 15 AS price UNION

SELECT 1 , 10 UNION

SELECT 2 , 8 UNION

SELECT 3 , 20;

CREATE TABLE sales AS

SELECT 3 AS user_id, 2 AS product_id UNION

SELECT 3 , 1 UNION

SELECT 1 , 0 UNION

SELECT 0 , 3 UNION

SELECT 4 , 3 UNION

SELECT 3 , 3 UNION

SELECT 1 , 3 UNION

SELECT 2 , 0;

(a) (4 pt)

CREATE TABLE t AS

SELECT u.name

FROM users AS u, sales AS s

WHERE u.user_id = s.user_id

GROUP BY u.user_id

ORDER BY COUNT(*) DESC

LIMIT 1;

What is the value of the one row in the table t and what does this value represent?

Daenerys The person with the most number of purchases.

(b) (6 pt) Create a table called large_spenders that contains the name and amount spent by everyone who
spent at least $25

CREATE TABLE large_spenders AS

SELECT u.name AS name, SUM(price) AS amount_spent

FROM users AS u, products AS p, sales AS s

WHERE u.user_id = s.user_id AND p.product_id = s.product_id

GROUP BY u.user_id

HAVING SUM(price) >= 25;

10

10. (6 points) Scheme

Modify scheme so that it keeps track of the number of times each procedure is called inside the evaluator. You
will also add the primitive call-count that takes a procedure as its argument and returns the number of times
the procedure has been called since the evaluator was started. This feature should work for both primitive and
compound procedures. For example:

scm> (define (foo x)

(* 2 (+ 1 (* 2 x))))

scm> (call-count foo)

0

scm> (call-count *)

0

scm> (foo 2)

10

scm> (call-count foo)

1

scm> (foo 10)

42

scm> (call-count foo)

2

scm> (call-count *)

4

scm> (call-count (lambda (x) x))

0

Your job is to modify the interpreter to make this work. We have provided several possibly relevant functions
on the following pages. (You might not need all the lines!)

Name: 11

CC = {}

def scheme_call_count(procedure):

if procedure in CC:

return CC[procedure]

return 0

def scheme_apply(procedure, args, env):

“””Apply Scheme PROCEDURE to argument values ARGS (a Scheme list) in

environment ENV.”””

check_procedure(procedure)

if procedure in CC:

CC[procedure] += 1

else:

CC[procedure] = 1

if isinstance(procedure, BuiltinProcedure):

return procedure.apply(args, env)

else:

new_env = procedure.make_call_frame(args, env)

return eval_all(procedure.body, new_env)

def create_global_frame():

“””Initialize and return a single-frame environment with built-in names.”””

env = Frame(None)

env.define(‘call-count’, BuiltinProcedure(scheme_call_count))

env.define(‘apply’, BuiltinProcedure(scheme_apply))

env.define(‘map’, BuiltinProcedure(scheme_map))

return env