cs 61a structure and interpretation of computer programs ...shidi/cs61a/61a-fa13-midterm2... · cs...

12
CS 61A Structure and Interpretation of Computer Programs Fall 2013 Midterm 2 INSTRUCTIONS You have 2 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 two 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 stause only Q. 1 Q. 2 Q. 3 Q. 4 Total /14 /14 /12 /10 /50 ,YERK %RHVI[ GWEX^ .SLR *VMHE] TQ %RHVI[ ,YERK *SVIZIV %PSRI ;%0/8,639+,

Upload: vuxuyen

Post on 09-Dec-2018

224 views

Category:

Documents


0 download

TRANSCRIPT

CS 61A Structure and Interpretation of Computer Programs

Fall 2013 Midterm 2

INSTRUCTIONS

• You have 2 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 two o�cial 61A midterm study guides attached to the back of thisexam.

• Mark your answers ON THE EXAM ITSELF. If you are not sure of your answer you may wish to provide abrief explanation.

Last name

First name

SID

Login

TA & section time

Name of the person toyour left

Name of the person toyour right

All the work on this exam

is my own. (please sign)

For sta↵ use only

Q. 1 Q. 2 Q. 3 Q. 4 Total

/14 /14 /12 /10 /50

,YERK

%RHVI[

GW��E�X^

.SLR�*VMHE]��TQ

%RHVI[�,YERK

*SVIZIV

%PSRI���

��������

;%0/8,639+,

2

1. (14 points) Classy Costumes

For each of the following expressions, write the value to which it evaluates. The first two rows have been providedas examples. If evaluation causes an error, write Error. If evaluation never completes, write Forever.

Assume that you have started Python 3 and executed the following statements:

class Monster:

vampire = {2: ’scary’}

def werewolf(self):

return self.vampire [2]

class Blob(Monster ):

vampire = {2: ’night’}

def __init__(self , ghoul):

vampire = {2: ’frankenstein ’}

self.witch = ghoul.vampire

self.witch [3] = self

spooky = Blob(Monster)

spooky.werewolf = lambda self: Monster.vampire [2]

Expression Evaluates to

square(5)

25

1/0

Error

[k+2 for k in range(4)]

Monster.vampire[2][3]

repr(len(spooky.witch))

spooky.witch[3] is not spooky

spooky.witch[2][0:4]

spooky.werewolf()

Monster.werewolf(spooky)

7XIT����6IEH�ERH�YRHIVWXERH�XLI�UYIWXMSR

7XIT����KPERGI�EX�XLI�TVSZMHIH�GSHI���8LMRKW�XS�RSXI�EX�¾VWX�KPERGI�������XLIVI�EVI�X[S�GPEWWIW��1SRWXIV�ERH�&PSF�������&PSF�MRLIVMXW�JVSQ�1SRWXIV������8LIVI�MW�XLMW�GSQTPMGEXMIH�QIWW�[MXL�ZEQTMVIW��

?����������A ����0MWX�GSQTVILIRWMSR��TVIXX]����WXVEMKLXJSV[EVH�MJ�]SY�ORS[�XLIQ

7XIT����8EGOPI�XLI�TVSFPIQW�

2SXMGI�1SRWXIV�MW�XLI�GPEWW

8LEX�QIERW�XLMW��ZEQTMVI��MW�_����WGEV]������WTSSO]a

7XIT����*MKYVI�SYX�[LEX�W�KSMRK�SR�[MXL�XLI�QIWW]�FMXW��WTSSO]�MW�E�MRWXERGI�SJ�XLI�&PSF�GPEWW��*SV�[LEXIZIV�VIEWSR���[I�VI�TEWWMRK�MR�XLI�1SRWXIV�GPEWW�EW�EVKYQIRX��WS�KLSYP�MW�1SRWXIV���3YV�RI[�SFNIGX�LEW�ER�MRWXERGI�ZEVMEFPI�[MXGL�WIX�IUYEP�XS��KLSYP�ZEQTMVI�!"�XLI�HMGXMSREV]�_����WGEV]�a

8LMW�MW�E�PSGEP�ZEVMEFPI������"ERH�HSIWR�X�E½IGX�ER]XLMRKMR�XLIWI�TEVXMGYPEV�TVSFPIQW

_����WGEV]������WTSSO]a

8LIWI�PMRIW�GEYWIW�XLI�GLERKIW�MR�VIH�EFSZI�

QSVI�EGGYVEXIP]��XLI�SFNIGX�XLEX�WTSO]�TSMRXW�XS

�V�1SRWXIV�ZEQTMVI?�A�KMZIW�YW��WGEV]�-RHI\MRK�MRXS�WPSX���SJ�XLI�WXVMRK�KMZIW�YW��V�

8LMW�VERKI�QIERW�����������

8LMW�MW�XLI�HMGXSREV]�_����WGEV]������WTSSO]a��� 2SXMGI�XLMW�MW�E�WXVMRK��WMRGI�VITV�EP[E]W

VIXYVRW�E�WXVMRK

*EPWI%KEMR��XLMW�MW�XLI�HMGXMSREV]�_����WGEV]������WTSSO]a

[LMGL�QEOIW�XLMW�WTSSO]

�WGEV]��WGEV�

6IQIQFIV�XLI�WPMGMRK�STIVEXMSR?WXEVX�IRHA�KSIW�WXEVX�MRGPYWMZI�XSIRH�I\GPYWMZI

8LMW�¿EX�SYX�IVVSVW�FIGEYWI�XLMW�[IVI[SPJ�MWR�XE�FSYRH�QIXLSH��7IEVGL��FSYRH�QIXLSH��SR4ME^^E�JSV�HIXEMPW

�RMKLX�;I�YWI�XLI�[IVI[SPJ�QIXLSH�MR�1SRWXIV�ERHTEWW�MR�WTSSO]��8LYW�WIPJ�MW�WTSSO]��ERMRWXERGI�SJ�XLI�&PSF�GPEWW ��1SRWXIV�[IVI[SPJVIXYVRW�WIPJ�ZEQTMVI?�A��[LMGL�IZEPYEXIW�XSXLI�ZEQTMVI�WXEXMG�ZEVMEFPI�EFSZI�MR�KVIIR�

5YIWXMSR�WE]W��[LEX�[MPP�4]XLSR�SYXTYX#�

Login: 3

2. (14 points) Wreaking Ball

(a) (8 pt) Fill in the environment diagram that results from executing the code below until the entire programis 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, labels, and parent annotations to all local frames.

• Add all missing values created during execution.

• Show the return value for each local frame.

Global frame

miley func miley(ray)

Return Value

Return Value

Return Value

Return Value

def miley(ray): def cy(): def rus(billy): nonlocal cy cy = lambda: billy + ray return (1, billy) if len(rus(2)) == 1: return (3, 4) else: return (cy(), 5) return cy()[1]billy = 6miley(7)

billy 6

7XIT����KMZIR�QMPI]�� �IZEPYEXI�XLI�STIVEXSV�ERH�STIVERHW���QMPI]�XYVRW�SYX�XS�FI�XLI�QMPI]�JYRGXMSR�����MW�WIPJ�IZEPYEXMRK8LMW�WXIT�MW�WS�YXXIVP]�MQTSVXERX�(SR�X�IZIV�JSVKIX�XS�I\TPMGXP]�GEVV]�SYX�XLMW�WXIT�IZIR�MJ��EW�MR�XLMW�GEWI��MX�W�WMQTPI�

7XIT����'VIEXI�J���XLI�JVEQI�GVIEXIH�JSV�QMPI]�� ��8LI�TEVIRX�SJ�J��MW�KPSFEP��XLI�TEVIRX�SJ�QMPI]

J� QMPI] TEVIRX�!�+PSFEP

VE] �

7XIT����FMRH�XLI�JSVQEP�TEVEQIXIV��VE] �XS��XLI�EGXYEP�EVKYQIRX�ZEPYI���

T�!�+PSFEP

G]JYRG�G]�FMPP] �TEVIRX�!�J�

7XIT����GVIEXI�XLMW�RI[�JYRGXMSR�G]��[LSWI�TEVIRX�MW�XLI�GYVVIRXJVEQI��J�

78%68�,)6)���

7XIT����IZEPYEXI�G]� ?�AF]�¾VWX�IZEPYEXMRK�G]� �G]�MW�XLI�G]�JYRGXMSR�MR�J��;I�GVIEXI�E�RI[�JVEQIJ��[LSWI�TEVIRX�MW�XLITEVIRX�SJ�G]��J���8LMW�MWXLI�RI[�GYVVIRX�JVEQI�

J� G] TEVIRX�!�J�

JYRG�VYW�FMPP] ���TEVIRX�!�J�

VYW

7XIT����'VIEXI�XLI�JYRGXMSR�VYW�[LSWI�TEVIRX�MW�XLI�GYVVIRX�JVEQI��J��

J� VYW

FMPP] �TEVIRX�!�J�

7XIT����HS�XLI�MJ�WXEXIQIRX�MR�G]�[LMGL�GEYWIW�YW�XS�IZEPYEXI�VYW�� VYW�MW�XLI�JYRGXMSR�MR�J�����MW���'VIEXI�E�RI[�JVEQI�J��[LSWITEVIRX�MW�XLI�TEVIRX�SJ�VYW��J���8LMW�MWXLI�RI[�GYVVIRX�JVEQI�

7XIT����XLI�RSRPSGEP�G]�GEYWIWG]�XS�FI�VIFSYRH�XS�E�PEQFHE�JYRGXMSR�'VIEXI�XLI�PEQFHE�JYRGXMSRXLEX�XEOIW�MR�RS�EVKYQIRXW��[LSWITEVIRX�MW�XLI�GYVVIRX�JVEQI��J��

7XIT����FMRH�FMPP]�XS���7XIT����VIXYVR�����FMPP] ��FMPP]�IZEPYEXIW�XS����WSHVE[�X[S�FS\IW�XS�VITVIWIRX�XLI�XYTPI��7MRGI�VYWVIXYVRIH��XLI�GYVVIRX�JVEQI�KSIW�FEGO�XSFIMRK�J���XLI�JVEQI�XLEX�GEPPIH�VYW�

JYRGXMSR�PEQFHE� �TEVIRX�!�J�

7XIT�����2S[�¾REPP]�KIX�FEGO�XS�XLEX�MJ�WXEXIQIRX�MR�G]��7MRGI�VYW�� VIXYVRW�E�XYTPI��ERH�XLI�PIR�SJ�XLEX�XYTPI�MW����[LMGL�MW�RSX�IUYEP�XS���VIXYVR��G]� ��� �-R�SVHIV�XS�VIXYVR�XLI�XYTPI��G]� ��� ��¾VWX�IZEPYEXI�G]� �

7XIT�����-R�SVHIV�XS�IZEPYEXI�G]� ��¾VWX�IZEPYEXI�XLI�STIVEXSV��+9)77�;,%8#�G]�MW�RS[�XLI�PEQFHE�JYRGXMSR�JVSQ�WXIT���830(�=39�):%09%8-2+�8,)�34)6%836�%2(�34)6%2(7�-7�-1436%28��%R][E]W��GVIEXI�E�RI[�JVEQI�J��JSV�G]��[LSWITEVIRX�MW�J���XLI�TEVIRX�SJ�XLI�PEQFHE��8LMW�MW�XLI�RI[�GYVVIRX�JVEQI

J� PEQFHE TEVIRX�!�J�

7XIT�����IZEPYEXI�XLI�FSH]�SJ�XLI�PEQFHE�MR�XLI�GSRXI\X�SJ�XLMW�GYVVIRX�JVEQI��0SSO�YT�FMPP]�ERH�MX�IZEPYEXI�XS���0SSO�YT�VE]�ERH�IZEPYEXI�MX�XS����6IXYVR����8LI�GYVVIRX�JVEQI�KSIW�FEGO�XS�FIMRK�J���XLI�JVEQI�XLEX�GEPPIH�XLI�PEQFHE�

7XIT�����31+�;-00�8,-7�2):)6�)2(#�PSP��2S[�XLEX�G]� �LEW�FIIR�IZEPYEXIH��¾REPP]�VIXYVR�XLI�XYTPI�SJ���ERH���2S[�XLI�GYVVIRX�JVEQI�KSIW�FEGO�XS�FIMRK�J���XLI�JVEQI�XLEX�GEPPIH�G]�

7XIT�����FEGO�MR�J���VIXYVR������ ?�A�!"����%RH�XLIR�KMZI�]SYVWIPJ�E�TEX�SR�XLI�FEGO��]SY�GLEQT�

5YIWXMSR�WE]W��(VE[�ER�IRZMVSRQIRX�HMEKVEQ��

4

(b) (6 pt) Write the letter of the environment diagram that would result from executing each code snippetbelow, just after starting Python. The first blank is filled for you. Two di↵erent snippets may result in thesame environment diagram. If none of the environment diagrams are correct, write N.

A

A

B

C

D

F

N: None of the above

Global frame

s

t

list10

1list

10

2

1 2

Global frame

s

t

Global frame

s

t

list0

list10

1

list0

list0

list10

1

list0

list0

Global frame

s

t

list0

list10

1

list0

Global frame

s

t

list0

list10

1 2list0

list0

EGlobal frame

s

t

list0

list10

1 2list0

8LI�SRP]�EHZMGI�-�LEZI�JSV�]SY�LIVI�MW�XS�HVE[�SYX�IEGL�SJ�XLI�WXVYGXYVIW��ERH�XLIR�QEXGL�XLIQ�

* ' (

*SV�IEGL�SJ�XLIWI��W�TSMRXW�XS�E�PMWX�SJ�SRI�IPIQIRX��E�PMWX�[MXL�X[S�IPIQIRXW����ERH��

X�TSMRXW�XS�XLEX�MRRIV�PMWX

XLI�¾VWX�IPIQIRX�SJ�X�MW�RS[E�RI[�PMWX�[MXL�SRI�IPIQIRX��W

X�TSMRXW�XS�XLI�WEQI�PMWX�XLEX�W�HSIW

XLI�WIGSRH�IPIQIRX�SJ�XLI�MRRIV�PMWXMW�RS[�E�RI[�PMWX�[MXL�SRI�IPIQIRX��W

X�TSMRXW�XS�E�RI[�PMWX�SJ�SRI����������������IPIQIRX��W

2S[�XLI�¾VWX�IPIQIRX�SJ�XMW�E�RI[�PMWX�SJ�SRI�IPIQIRX��W

5YIWXMSR�WE]W��(VE[�FS\�ERH�TSMRXIVW�

Login: 5

3. (12 points) Mutants

(a) (4 pt) Given two Rlist arguments a and b, the function merge(a, b) changes a so that it also includesall elements of b at the end, but does not change b. After merging, changes to b should not a↵ect a.Assume that a is not empty, but b may be empty. Complete the implementation by filling the blanks withexpressions. The Rlist class is defined in your study guide.

def merge(a, b):

""" Add the elements of b to the end of a, mutating a but not b.

>>> a = Rlist(1, Rlist(2, Rlist (3)))

>>> b = Rlist(4, Rlist(5, Rlist (6)))

>>> merge(a, b)

>>> a # a should be modified

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

>>> b # b should not be modified

Rlist(4, Rlist(5, Rlist (6)))

>>> b.first = 7 # modify the elements of b

>>> b # b should be modified

Rlist(7, Rlist(5, Rlist (6)))

>>> a # a should not be modified

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

"""

assert a is not Rlist.empty

if b is Rlist.empty:

return # No entries to add to a.

elif _________________________________________________________:

__________________________________________________________

__________________________________________________________

else:

__________________________________________________________

(b) (2 pt) Define a mathematical function f(m,n) such that evaluating a correct and e�cient implementationof merge(a, b) on Rlist a of length m and Rlist b of length n requires ⇥(f(m,n)) function calls.

f(m,n) =

5YIWXMSR�WE]W��[VMXI�QIVKI���[MXL�GEZIEXW

8LMW�QIERW�[I�LEZI�XS�GSRWXVYGXE�RI[�PMWX�XS�LSSO�SRXS�E�

7XIT����%WWIWW�XLII\EQTPIW

7XIT����6IEH�ERH�YRHIVWXERH�XLI�UYIWXMSR

8LI�HSGXIWXW�SR�I\EQW�XIPP�]SY�I\EGXP][LEX�XLI�UYIWXMSR�MW�EWOMRK

7XIT����%WWIWW�XLIGSHI�KMZIR

Q�R -X�XEOIW�Q�VIGYVWMZI�GEPPW�XS�KIX�XS�XLI�IRH�SJ�XLI�¾VWX�PMWXERH�R�VIGYVWMZI�GEPPW�XS�GSRWXVYGX�E�GST]�SJ�XLI�WIGSRH�PMWX�

,IVI�W�E�FEWI�GEWI��7MRGI�E�MW�RSRIQTX]��[I�SRP]�[SVV]�EFSYX�F

8LMW�QYWX�FI�XLI�GEWI�[LIVI�F�MWR�X�IQTX]��;LEX�KSIW�MR�XLMW�IPMJ#�,Q���7XIT����8LMRO�EFSYX�XLITVSFPIQ�MR�)RKPMWL8LI�FMK�MHIE�MW�XLEX�[I�WSQILS[LEZI�XS�KIX�XS�XLI�IRHSJ�E�ERH�XLIR�QSHMJ]�XLI�IRH�SJE�WS�XLEX�[I�GVIEXI�ERH�EXXEGLE�RI[�PMWX�XLEX�LEWXLI�IPIQIRXW�SJ�F�MR�MX�

7XIT����8VERWPEXI�MRXS�4]XLSR3OE]��LS[�HS�[I�XVEZIVWI�E#�;LIR�HS�[I�ORS[�[LIR�[I�VI�EX�XLI�IRH�SJ�E#�3L��;LIR�E�VIWX�MW�IQTX]�;I�GER�EWWYQI�E�[SR�X�IZIV�IQTX]��JVSQ�XLI�TVSFPIQ�WXEXIQIRX ��WS�MX�PP�LEZI�E�VIWX�

E�VIWX�MW�6PMWX�IQTX]-J�XLI�VIWX�MW�IQTX]��XLIR�[I�WLSYPH�WXEVX�XLI�QIVKMRK��7MRGI[I�LEZI�XS�QEOI�E�GST]�SJ�F��[I�[MPP�QEOI�E�RI[�6PMWX��;IGER�SRP]�VIEPP]�QEOI�SRI�IPIQIRX�EX�E�XMQI��0IX�W�WXEVX�[MXL�XLI¾VWX�IPIQIRX�

E�VIWX�!�6PMWX�F�¾VWX

,S[�HS�[I�LERHPI�IZIV]XLMRK�IPWI#�6IGYVWMSR�QIVKI�E�VIWX��F�VIWX

-J�XLI�IPMJ�GLIGOIH�XLEX�E�VIWX�MW�IQTX]��XLIR�XLMW�MW�XLI�GEWI�[LIVI�MX�MWR�X��;I�LEZIR�X�KSXXIRXS�XLI�IRH�SJ�E�]IX�

QIVKI�E�VIWX��F 7XIT����8IWX�XIWX�XIWX�0IX�W�NYWX�GLIGO�SYX�XLI�HSGXIWX��-J�[I�HS�QIVKI�E��F ��XLI�VIGYVWMZI�GEPPW�[MPP�OIIT�LMXXMRK�XLI�IPWI�GEWI

YRXMP�[I�VI�EX�XLI�6PMWX�GSRXEMRMRK����8LIR�[I�WIX�MXW�VIWX�XS�6PMWX�� ��ERH�XLIR�HS�XLEX�EKEMR�JSV���ERH���

6(c) (6 pt) The function fold_tree takes in a three-argument function, a zero value, and a Tree. It returns

the value of replacing Tree with the function and empty branches with the zero value. For each of size,reverse, and repeated, complete the inner function f. Each f cannot be recursive.

def fold_tree(fn , zero , tree):

""" Replaces the tree constructor with a 3-argument function.

>>> t = Tree(3, Tree(5, None , Tree (3)), Tree (2))

>>> f = lambda a, b, c: a + b + c

>>> fold_tree(f, 0, t) # is equivalent to the expression ...

13

>>> f(3, f(5, 0, f(3, 0, 0)), f(2, 0, 0))

13

"""

if tree is None:

return zero

return fn(tree.entry , fold_tree(fn , zero , tree.left),

fold_tree(fn , zero , tree.right ))

def size(tree):

""" Return the number of trees contained in tree.

>>> size(Tree(3, Tree(5, None , Tree (3)), Tree (2)))

4

"""

def f(entry , left , right):

return fold_tree(f, 0, tree)

def reverse(tree):

""" Return a new tree swapping all left and right branches of tree.

>>> reverse(Tree(3, Tree(5, None , Tree (3)), Tree (2)))

Tree(3, Tree(2), Tree(5, Tree(3), None))

"""

def f(entry , left , right):

return fold_tree(f, None , tree)

def repeated(tree):

""" Return how many times the root entry of tree appears in tree.

>>> repeated(Tree(3, Tree(5, None , Tree (3)), Tree (2))) # 3 appears twice

2

"""

def f(entry , left , right):

return fold_tree(f, 0, tree)

7XIT����6IEH�ERH�YRHIVWXERH�XLI�UYIWXMSR

�;I�LEZI�XLMW�JYRGXMSR�JSPH�XVII�XLEX�HSIW�WSQIXLMRK�GVE^]�[MXL�XVIIW��;I�VI�WYTTSWI�XS�YWI�MX��

7XIT����9RHIVWXERHXLI�I\EQTPIW�ERHTVSZMHIH�GSHI�

JSPHCXVII�XEOIW�MR�E�JYRGXMSR��WSQI�RYPP�ZEPYI��ERH�E�XVII

-X�PSSOW�PMOI�JSPHCXVII�VIXYVRW�E�ZEPYI�[MXL�XLI�WEQI�X]TI�EW�^IVS

8LEX�QIERW�JR�QYWXXEOI�MR�XLVII�XLMRKW��EPP�SJ�XLI�WEQI�X]TI�EW�^IVS

8VII�6IGYVWMSR�;I�QEOI�VIGYVWMZI�GEPPWSR�XLI�PIJX�ERH�VMKLX�8LMW�QIERW�[I�PP�KS�XLVSYKLXLI�IRXMVI�XVII�

&EWIH�SR�XLI�I\EQTPI�X�!������������������@��������������������@���������

J�MW�E�JYRGXMSR�XLEX�XEOIW�XLVII�XLMRKW�ERH�EHHW�XLIQ�YT

;LIR�[I�GEPP�JSPHCXVII��[I�TEWW�MR�J��E�PMXIVEP����ERH�XLI�I\EQTPI�XVII

3OE]��WS�-�ORS[�XLEXJSPHCXVII�HSIW�WSQIWSVX�SJ�XVII�VIGYVWMSRJSV�QI�ERH�GSQFMRIWXLMRKW�XSKIXLIV�

7XIT����9WI�XLI�I\EQTPIW�ERH�XLI�HSGWXVMRK�XS�YRHIVWXERH�LS[�XS�YWI�JSPHCXVII

-�ORS[�-�LEZI�XS�YWI�JSPH�XVII�ERH�XLEX�MX�[MPP�XVEZIVWI�XLI�XVIIERH�GEPP�J�EX�IEGL�IRXV]�

0SSO��XLI]�IZIR�KEZI�YW�XLI�^IVS�

VIXYVR�����PIJX���VMKLX*VSQ�EFSZI��-�ORS[�XLEX�PIJX�ERH�VMKLX�[MPP�FI�XLI�WEQI�X]TI�EW�XLI�^IVS��WS�E�RYQFIV�

7XIT����8IWX�XIWX�XIWX�

;I�[ERX�E�RYQFIV�EX�XLI�IRH�

8LI�I\EQTPI�XVII�MWXLI�WEQI�EW�XLI�SRI�EFSZI�-J�[I�GEPP�WM^I�SR�MX��[IXVEZIVWI�XLI�IRXMVI�XVIIERH�JSV�IEGL�IRXV]�EHH���

7XIT����6ITIEX�

VIXYVR�8VII�IRXV]��VMKLX��PIJX

-X�PSSOW�PMOI�[I�[ERX�XS�VIXYVR�E�8VII�EX�XLI�IRH�2SRI�MW�LS[�[I�VI�VITVIWIRXMRK�XLI�IQTX]�XVII�LIVI���WSXLEX�QEOIW�WIRWI��-R�SVHIV�XS�W[MXGL�XLI�PIJX�ERH�VMKLX�[I�NYWX�W[MXGL�XLI�EVKYQIRXW�

��8LMW�MW�EGXYEPP]�E�WPMKLX�HEXE�EFWXVEGXSMR�ZMSPEXMSR����&EH���%�WXE½�

MJ�XVII�IRXV]�!!�IRXV]�����VIXYVR�����PIJX���VMKLXIPWI�����VIXYVR�PIJX���VMKLX

,IVI�[I�[ERX�E�GSYRX��WS�[I�WLSYPH�SYXTYX�E�RYQFIV�;I�EP[E]W�LEZI�EGGIWW�XS�XLI�IRXV]�EX�XLI�VSSX��XVII�IRXV] �IRXV]�MW�ER�EVKYQIRX�XS�J�ERH�MX�[MPP�FI�IEGL�IRXV]�MR�XLIIRXMVI�XVII��;I�GER�GSQTEVI�XLI�GYVVIRX�IRXV]�[MXL�XVII�IRXV]XS�¾KYVI�SYX�[LIXLIV�SV�RSX�[I�[ERX�XS�GSYRX�XLI�GYVVIRXIRXV]��F]�EHHMRK�� �

Login: 7

4. (10 points) Expansion Mansion

For a fraction n/d with n < d, its decimal expansion is written as a series of digits following a decimal point.

For example, 5/8 expands to 0.625. We can compute this result recursively. The numerator 5 times 10 is 50. 50divided by 8 is 6 with remainder 2. 20 divided by 8 is 2 with remainder 4. 40 divided by 8 is 5 with remainder0. The quotients in bold are the digits of the expansion. Each subsequent digit is the quotient of dividing 10times the remainder of the previous digit by the denominator of the fraction.

(a) (4 pt) Assume that the decimal expansion of n/d is finite, n is positive, and n < d. The functionexpand_finite returns the digits of the decimal expasion as an Rlist. Complete it by filling in eachblank with an expression. The Rlist class is defined in your study guide.

def expand_finite(n, d):

""" Return the finite decimal expansion of n/d as an Rlist. Assume n<d.

>>> expand_finite (1, 2) # 1/2 = 0.5

Rlist (5)

>>> expand_finite (5, 8) # 5/8 = 0.625

Rlist(6, Rlist(2, Rlist (5)))

>>> expand_finite (3, 40) # 3/40 = 0.075

Rlist(0, Rlist(7, Rlist (5)))

"""

dividend = n * 10

quotient , remainder = dividend // d, dividend % d

if _________________________________________________________________:

return _________________________________________________________

else:

return _________________________________________________________

(b) (2 pt) The function coerce_to_float returns the float equal to an input Rlist representing the seriesof digits following the decimal point in a finite decimal expansion. Complete its implementation below.

def coerce_to_float(s):

""" Return a float equal to an Rlist encoding a series of digits.

>>> coerce_to_float(expand_finite (1, 2))

0.5

>>> coerce_to_float(expand_finite (3, 40))

0.075

"""

if s is Rlist.empty:

return 0

else:

return ________________________________________________________

7XIT����6IEH�ERH�YRHIVWXERH�XLI�UYIWXMSR

5YIWXMSR�WE]W��;VMXI�E�VIGYVWMZI�JYRGXMSR�XLEX�HSIW�HMZMWMSR��

7XIT����%WWIWW�XLI)\EQTPIW

8LMW�I\EQTPI�MR�TEVXMGYPEV�MW�I\TPEMRIH�MR�XLITVSFPIQ�WXEXIQIRX��8LI�TVSFPIQ�KSIW�WXITF]�WXIT�ERH�I\TPEMRW�LS[�XLI�HMZMWMSR�[SVOW�

6)1)1&)6�(31%-2�%2(�6%2+)�

(SQEMR�LIVI�MWRYQFIVW

6ERKI�ETTIEVW�XS�FI�VPMWXW7XIT����%WWIWW�XLI�KMZIR�GSHI

.YWX�PMOI�MR�XLI�I\EQTPI�MR�XLI�TVSFPIQ�WXEXIQIRX��[I�XEOI�XLI�RYQIVEXSVERH�QYPXMTP]�MX�[MXL����¾VWX��*SV�I\EQTPI��MJ�R�!���ERH�H�!����XLIR�HMZMHIRH�!����

7XIT����8LMRO�EFSYXWSPZMRK�XLI�TVSFPIQFEWIH�SR�XLI�I\EQTPIW�VIEH�XLI�TYVTPI�XI\X

-J�R�!���ERH�H�!����XLIR�XLI�UYSXMIRX�!���ERH�VIQEMRHIV�!��MJ�R�!���ERH�H�!����XLIR�XLI�UYSXMIRX�!���������!���ERH�VIQEMRHIV�!��MJ�R�!���ERH�H�!����XLIR�XLI�UYSXMIRX�!���������!���ERH�VIQEMRHIV�!��8LVS[�EPP�XLI�UYSXMIRXW�MR�ER�6PMWX�WSQI[LS[�ERH�XLIR�[I�VI�HSRI�

2SXMGI�XLEX�XLI�VIQEMRHIVSJ�XLI�TVIZMSYW�GEPGYPEXMSR�FIGSQIWXLI�RI[�R��[LMPI�H�VIQEMRWXLI�WEQI

VIQEMRHIV�!!��

VIXYVR�6PMWX�UYSXMIRX

I\TERHC:RMXI�VIQEMRHIV��H 6PMWX�UYSXMIRX�

7S�RS[�[I�ORS[�XLI�VIGYVWMZI�GEPP��XLI�KVIIR ��FYX�MX�WXMPP�HSIWR�X�WIIQ�VMKLX���HSQEMR�ERH�VERKI�XS�XLI�VIWGYI��;I�ORS[�XLEX�I\TERHC¾RMXI�WLSYPH�VIXYVR�ER�6PMWX��VIH �

7XIT����8LMRO�EFSYX�XLI�XLMRKW�RIIHIH�JSVVIGYVWMSR��FEWI�GEWIW��VIGYVWMZI�GEPPW�ERH�[E]W�XS�QEOI�XLI�TVSFPIQ�WQEPPIV��-R�XLMW�GEWI�XLI�TVSFPIQ�LEW�FIIR�FVSOIR�HS[R�MRXS�XLIVIQEMRHIV�ERH�XLI�HMZMHIRH�

&EWI�GEWI��[LEX�W�XLI�WMQTPMIWX�GEWI�JSVI\TERHC¾RMXI#�;LIR�EVI�[I�HSRI#

,IVI�XLI�FEWI�GEWI�MW�KMZIR�XS�YW�;I�NYWX�RIIH�XS�:KYVI�SYX�XLI�VIGYVWMZIGEWI�ERH�LS[�XLI�TVSFPIQ�VIHYGIW�XS�MX�

GSIVGICXSC¿SEX�W�VIWX

0IX�W�NYWX�XV]�XLI�HYQF�XLMRK�

7XIT����8IWX8IWX�8IWX�I\TERH����� !"�6PMWX��

I\TERH������ !"�6PMWX����I\TERH������� ��!"�6PMWX����I\TERH������� ���!"�6PMWX�� !"�6����6����6��

(MHR�X�[SVO��(SGXIWXW�VIXYVRIH����;I�VI�QMWWMRK�WSQIXLMRK��0IX�W�XV]�EHHMRK�W�¾VWX�

��W�¾VWX

7XMPP�RSX�UYMXI��8LI�¾VWX�HSGXIWX�VIXYVRW����,S[�HS�[I�KIX�E�HIGMQEP#�0IX�W�XV]�WSQIXLMRK�HYQF���3L�LI]��XLI�XIWXW�TEWW�

� �����

8

Repeating Decimal Expansions. The decimal expansion of a rational number may be infinite, butcan always be described by a finite (and possibly repeating) series of digits. We can represent a series ofdigits as a recursive list, which may contain itself.

(c) (4 pt) Assume that n is positive and n < d. The expand function returns representations of both finiteand infinite decimal expansions. Complete it by filling in each blank with an expression or assignmentstatement.

def expand(n, d):

""" Return the decimal expansion of n/d as an Rlist. Assume n < d.

>>> expand(1, 2) # 1/2 = 0.5

Rlist (5)

>>> expand(5, 8) # 5/8 = 0.625

Rlist(6, Rlist(2, Rlist (5)))

>>> third = expand(1, 3) # 1/3 = 0.333333...

>>> [third[i] for i in range (10)]

[3, 3, 3, 3, 3, 3, 3, 3, 3, 3]

>>> third.rest is third # There is only one unique digit in 1/3

True

>>> fourteenth = expand(1, 14) # 1/14 = 0.0714285714285...

>>> [fourteenth[i] for i in range (10)]

[0, 7, 1, 4, 2, 8, 5, 7, 1, 4]

"""

return expand_using(n, d, {})

def expand_using(n, d, known):

""" Return the decimal expansion of n/d as an Rlist.

known -- a dictionary from integer k to the decimal expansion of k/d.

"""

if n in known:

return known[n]

else:

dividend = n * 10

quotient , remainder = dividend // d, dividend % d

digits = ________________________________________________________

_________________________________________________________________

if ______________________________________________________________:

_____________________________________________________________

return digits

7XIT����6IEH�ERH�YRHIVWXERH�XLI�UYIWXMSR

;EMX����HMHR�X�[I�NYWX�HS�XLMW#�;LEX�W�HM½IVIRX�LIVI#�;VMXI�E�VIGYVWMZI�JYRGXMSR�XLEX�HSIW�HMZMWMSR��

;EEEEEX#

7XIT����%WWIWW�XLII\EQTPIW��-R�XLMWGEWI��XLMW�LIPTW�YWHS�7XIT���QYGLFIXXIV��7II�KVIIR�

7S�XLIWI�¾VWX�X[S�I\EQTPIW�EVI�XLI�WEQI�EW�FIJSVI

,IVI�W�[LIVI�XLMRKW�KIX�XVMGO]��;LEX�HSIW�XLMW�QIER#

0IX�W�XV]�HVE[MRKSYX�[LEX�XLMVH�MW�

XLMVH

7XIT����%WWIWW�XLIKMZIR�GSHI��VIH �

7S�IZIRXYEPP]��[I�PP�GEPP�I\TERHCYWMRK�[MXLR��H�ERH�ER�IQTX]�HMGXMSREV]

8LIVI�W�E�LIPTIVJYGXMSR��I\TERHCYWMRK�;I�VI�WYTTSWI�XS�[VMXIMX#�SC3

;LEX�MW�I\TERHCYWMRKXV]MRK�XS�HS#�#

-X�PSSOW�PMOI�I\TERHCYWMRK�MW�HSMRK�EPP�XLI�[SVO��;L]�HS�[I�RIIH�XLMWHMGXMSREV]#�0IX�W�PSSO�EX�XLI�GSHI���

-J�SYV�R�MW�MR�XLMW�HMGXMSREV]�VIXYVR�XLI�ZEPYI#�%XPIEWX�[I�ORS[�SYVOI]W�EVI�KSMRK�XS�FIR�W

� �

8LMW�PSSOW�JEQMPMEV����MX�W�XLI�WEQI�GSHI�JVSQ��E�

7XIT����'SRWMHIV�HSQEMRERH�VERKI�ERH�EPWS�XLIXLMRKW�RIGIWWEV]�JSVVIGYVWMSR���KVIIR

;I�ORS[�XLEX�[I�VIXYVR�HMKMXW�EX�XLI�IRH�ERH�I\TERHCYWMRK�1978�VIXYVR�ER�6PMWX��WS�HMKMXW�QYWX�FI�ER�6PMWX�

6PMWX�UYSXMIRX�I\TERHCYWMRK�VIQEMRHIV��H��ORS[R

7XIT����8V]�XLMRKW�XIWX�XLIQ�SYX��RSXMGI�XLEXXLI]�VI�FVSOIR��ERH�:\XLIQ�6ITIEX�MJ�RIGIWWEV]��G]ER��SVERKI��ERH�TYVTPI 0IX�W�NYWX�XV]�XLI�SFZMSYW

XLMRK��;I�HMH�XLMW�MRI\TERHC¾RMXI�

;EMX��XLIR�[L]�EVI�XLIVIEPP�XLIWI�PMRIW�PIJX#;I�LEZIR�X�HSRI�ER]XLMRK[MXL�ORS[R�]IX�IMXLIV�-J�[I�OITX�XLI�G]ER�MR�[I�[SYPH�VIGYVWI�JSVIZIV��XIWX�[MXLI\TERHCYWMRK�������_a

8LI�HSGWXVMRK�WE]WXLEX�ORS[R�MW�E�HMGXMSREV][LSWI�OI]W�EVI�RYQFIVWERH�[LSWI�ZEPYIW�EVIHIGMQEP�I\TERWMSRW��6PMWXW� 0IX�W�XV]�XLI�WXYTMH�XLMRKXS�:PP�SYX�ORS[R�

ORS[R?RA�!�HMKMXW

&EWIH�SR�XLI�GSHI�VMKLXRS[��F]�XV]MRK�XLMRKW�SYX�[I�GER�SRP]�GSZIV�XLI�FEWI�GEWI�I\EQTPI�I\TERHCYWMRK�������_a �;LMGL�QIERW�XLEX�XLI�MJ�QYWX�FI�[LIVI�XLI�VIGYVWMZI�GEWI�MW�-J�XLI�FEWI�GEWI�MW�[LIVI�VIQEMRHIV�!!����XLIR�XLI�VIGYVWMZI�GEWI�MW�XLI�STTSWMXI�

VIQEMRHIV��!��

I\TERHCYWMRK�VIQEMRHIV��H��ORS[R

7XIT����8IWX�XIWX�XIWX���VIH 8IWXMRK�SYX�I\TERHCYWMRK�������_a �[SYPH�KMZI�YW�6PMWX�� ��8LEX�W�RSX�[LEX�[I�[ERX�;I�RIIH�XS�TSMRX�XLI�VIWX�SJ�XLI�VPMWX�XS�MXWIPJ��NYWX�PMOI�MR�XLI�FS\�ERH�TSMRXIV�HMEKVEQEFSZI��8LI�SRP]�[E]�XS�HS�XLEX�MW�XS�WE]�WSQI[LIVI�HMKMXW�VIWX����MX�W�RSX�MR�XLI�:VWX�PMRI�ERH�XLI�WIGSRH�PMRI�WIIQW�XS�FI�HSMRK�WSQIXLMRK�XLEX�[I�HSR�X�[ERX�XS�QIWW�[MXL�0IX�W�TYX�XLMW�SR�XLI�PEWX�PMRI�ERH�XIWX�EKEMR����3OE]��8LMW�XMQI�MX�[SVOW�

HMKMXW�VIWX�!

CS 61A Midterm 1 Study Guide – Page 1

208mul(add(2, mul(4, 6)), add(3, 5))

add(2, mul(4, 6))26mul

add 2mul(4, 6)

mul 4 6

24

add(3, 5)

add 3 5

8

-22

-2None

abs(number):

print(...):

display “-2”

2, 101024

pow(x, y):

Pure Functions

Non-Pure Functions

A name evaluates to the value bound to that name in the earliest frame of the current environment in which that name is found.

Defining:

Call expression:

square( x ):

return mul(x, x)

>>> def

square(2+2)

Calling/Applying: square( x ):

return mul(x, x)

Def statement

Formal parameter

Body

Return expression

(return statement)

operand: 2+2argument: 4

operator: squarefunction: func square(x)

Intrinsic name

4

16Argument

Return value

<header>: <statement> <statement> ... <separating header>: <statement> <statement> ... ...

Compound statement

Suite

Clause

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.

1. Evaluate the header’s expression.2. If it is a true value, execute the (whole) suite, then return to step 1.

Execution rule for while statements:

Execution rule for def statements:

Execution rule for assignment statements:

Evaluation rule for call expressions:

Execution rule for conditional statements: hof.py Page 2

return total

def identity(k): return k

def cube(k): return pow(k, 3)

def summation(n, term): """Sum the first n terms of a sequence. >>> summation(5, cube) 225 """ total, k = 0, 1 while k <= n: total, k = total + term(k), k + 1 return total

def pi_term(k): return 8 / (k * 4 − 3) / (k * 4 − 1)

# Local function definitions; returning functions

def make_adder(n): """Return a function that takes one argument k and returns k + n.

>>> add_three = make_adder(3) >>> add_three(4) 7 """ def adder(k): return k + n return adder

def compose1(f, g): """Return a function that composes f and g.

f, g −− functions of a single argument """ def h(x): return f(g(x)) return h

@maindef run(): interact()

Function of a single argument (not called term)

A formal parameter that will be bound to a function

The function bound to term gets called here

The cube function is passed as an argument value

0 + 13 + 23 + 33 + 43 + 55

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

Evaluation rule for or expressions:

Evaluation rule for and expressions:

Evaluation rule for not expressions:

Applying user-defined functions:

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.

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.

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.

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.

1.Evaluate the subexpression <left>.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 <right>.

1.Evaluate the subexpression <left>.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 <right>.

1.Evaluate <exp>; The value is True if the result is a false value, and False otherwise.

A name is bound to a value

In a frame, there is at most one binding per name

Statements and expressionsRed arrow points to next line.Gray arrow points to the line just executed

Frames (right):Code (left):

Import statement

Assignment statement

Name Value

Binding

Local frame

Intrinsic name of function called

Formal parameter bound to argument Return value is

not a binding!

Built-in function

User-defined function

2

1

“mul” is not found

2

1

3

1

2 1

Always extends

When a frame or function has no label

[parent=___]

then its parent is always the global

frame

Always extends

A three-frame environment

A two-frame environment

The global environment: the environment with only the global frame

A frame extends the environment that begins with its parent

2

1

“y” is not found

“y” is not found

Error

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 boolean contexts

•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

def make_adder(n): """Return a function that takes one argument k and returns k + n.

>>> add_three = make_adder(3) >>> add_three(4) 7 """ def adder(k): return k + n return adder

CS 61A Midterm 1 Study Guide – Page 2

A function that returns a function

A local def statement

The name add_three is bound to a function

Can refer to names in the enclosing function

square = lambda x,y: x * y

that returns the value of "x * x"with formal parameters x and y

A function

Must be a single expression

square = lambda x: x * x def square(x): return x * xVS

• 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.

Begin with a function f and an initial guess x

(x, f(x))

-f(x)/f'(x)

-f(x)

�� ���)�����

>>> f = lambda x: x*x - 2>>> df = lambda x: 2*x>>> find_zero(f, df)1.4142135623730951

How to find the square root of 2?

1. Compute the value of f at the guess: f(x)2. Compute the derivative of f at the guess: f'(x)3. Update guess to be:

from operator import floordiv, moddef divide_exact(n, d): """Return the quotient and remainder of dividing N by D.

>>> q, r = divide_exact(2012, 10) >>> q 201 """ return floordiv(n, d), mod(n, d)

Multiple return values, separated by commas

Multiple assignmentto two names

def improve(update, close, guess=1): """Iteratively improve guess with update until close(guess) is true.""" while not close(guess): guess = update(guess) return guess

def approx_eq(x, y, tolerance=1e-15): return abs(x - y) < tolerance

def find_zero(f, df): """Return a zero of the function f with derivative df.""" def near_zero(x): return approx_eq(f(x), 0) return improve(newton_update(f, df), near_zero)

def newton_update(f, df): """Return an update function for f with derivative df, using Newton's method.""" def update(x): return x - f(x) / df(x) return update

def power(x, n): """Return x * x * x * ... * x for x repeated n times.""" product, k = 1, 0 while k < n: product, k = product * x, k + 1 return product

def nth_root_of_a(n, a): """Return the nth root of a.""" def f(x): return power(x, n) - a def df(x): return n * power(x, n-1) return find_zero(f, df)

2

1

3

1

2

3

•Every user-defined function has a parent frame (often global)

•The parent of a function is the frame in which it was defined

•Every local frame has a parent frame (often global)

•The parent of a frame is the parent of the function called

A function’s signature has all the information to create a local frame

Evaluates to a function.No "return" keyword!

def curry2(f): """Returns a function g such that g(x)(y) returns f(x, y).""" def g(x): def h(y): return f(x, y) return h return g

• The def statement header is similar to other functions• Conditional statements check for base cases• Base cases are evaluated without recursive calls• Recursive cases are evaluated with recursive callsdef sum_digits(n):

"""Return the sum of the digits of positive integer n.""" if n < 10: return n else: all_but_last, last = n // 10, n % 10 return sum_digits(all_but_last) + last

Currying: Transforming a multi-argument function into a single-argument, higher-order function.

Is fact implemented correctly?1. Verify the base case.2. Treat fact as a functional abstraction! 3. Assume that fact(n-1) is correct.4. Verify that fact(n) is correct,

assuming that fact(n-1) correct.

def fact(n): if n == 0: return 1 else: return n * fact(n-1)

• Each cascade frame is from a different call to cascade.

• Until the Return value appears, that call has not completed.

• Any statement can appear before or after the recursive call.

def count_partitions(n, m): if n == 0: return 1 elif n < 0: return 0 elif m == 0: return 0 else: with_m = count_partitions(n-m, m) without_m = count_partitions(n, m-1) return with_m + without_m

• Recursive decomposition: finding simpler instances of the problem: partition(6, 4)• Explore two possibilities:• Use at least one 4• Don't use any 4• Solve two simpler problems:• partition(2, 4)• partition(6, 3)• Tree recursion often involves exploring different choices.

When a function is defined:1. Create a function value: func <name>(<formal parameters>)2. If the parent frame of that function is not the global frame,

add matching labels to the parent frame and the function value (such as f1, f2, or f3).

3. Bind <name> to the function value in the first frame of the current environment.

When a function is called:1. Add a local frame, titled with the <name> of the function being

called.2. If the function has a parent label, copy it to the local frame:

[parent=<label>]3. Bind the <formal parameters> to the arguments in the local frame.4. Execute the body of the function in the environment that starts

with the local frame.

CS 61A Midterm 2 Study Guide – Page 1

Numeric types in Python:

>>> type(2)<class 'int'>

>>> type(1.5)<class 'float'>

>>> type(1+1j)<class 'complex'>

Represents integers exactly

Represents real numbers approximately

•Exact representation of fractions•A pair of integers•As soon as division occurs, the exact representation may be lost!•Assume we can compose and decompose rational numbers:

numeratordenominator

•rational(n, d) returns a rational number x

•numer(x) returns the numerator of x

•denom(x) returns the denominator of x

Constructor

Selectors

Rational number:

These functions implement an abstract data typefor rational numbers

There isn't just one sequence class or abstract data type (in Python or in general).The sequence abstraction is a collection of behaviors:

Length. A sequence has a finite length.Element selection. A sequence has an element corresponding to any non-negative integer index less than its length, starting at 0 for the first element.

We can implement recursive lists as pairs. We'll use two-element tuples to encode pairs.

A recursive list is a pair

The first element of the pair is the first element

of the list

The second element of the pair is the rest of

the list

None represents the empty

list

1 , 2 , 3 , 4

for <name> in <expression>: <suite>

1.Evaluate the header <expression>, which must yield an iterable value.2.For each element in that sequence, in order:A. Bind <name> to that element in the first frame of the current

environment.B. Execute the <suite>.

Executing a for statement:

..., -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, ...

>>> tuple(range(-2, 2))(-2, -1, 0, 1)

>>> tuple(range(4))(0, 1, 2, 3)

A range is a sequence of consecutive integers.

range(-2, 2)Length: ending value - starting valueElement selection: starting value + index

Tuple constructor

With a 0 starting value

[<map exp> for <name> in <iter exp> if <filter exp>]Short version: [<map exp> for <name> in <iter exp>]

A combined expression that evaluates to a list by this procedure:1. Add a new frame extending the current frame.2. Create an empty result list that is the value of the expression.3. For each element in the iterable value of <iter exp>:

A. Bind <name> to that element in the new frame from step 1.B. If <filter exp> evaluates to a true value, then add the value of

<map exp> to the result list.

List comprehensions:

•Lists are mutable sequences•Tuples are immutable sequences•Dictionaries are unordered collections of key-value pairs.

•Sets are unordered collections of values.

•Two dictionary keys or set elements cannot be equal.

•A dictionary key or set element cannot be an instance of a mutable built-in type.

The "in" and "not in" operators match substrings

>>> 'here' in "Where's Waldo?"True>>> 234 in (1, 2, 3, 4, 5)False

>>> city = 'Berkeley'>>> len(city)8>>> city[3]'k'

An element of a string is itself a string, but with only one character!

Strings are sequences too:

A function with a non-global parent frame

The parent contains local state

Every call changes the balance

All calls to the same function have the same

parent

def make_withdraw(balance): """Return a withdraw function with a starting balance.""" def withdraw(amount): nonlocal balance if amount > balance: return 'Insufficient funds' balance = balance - amount return balance return withdraw

Declare the name "balance" nonlocal at the top of the body of the function in which it

is re-assigned

Re-bind balance in the first non-local frame in which it was bound

previously

>>> withdraw(25)75

>>> withdraw(25)50

x = 2Status Effect

•No nonlocal statement•"x" is not bound locally

•No nonlocal statement•"x" is bound locally

•nonlocal x•"x" is bound in a non-local frame•"x" also bound locally

•nonlocal x•"x" is not bound in a non-local frame

•nonlocal x•"x" is bound in a non-local frame

Create a new binding from name "x" to object 2 in the first frame of the current environment.

Re-bind name "x" to object 2 in the first frame of the current env.

SyntaxError: name 'x' is parameter and nonlocal

SyntaxError: no binding for nonlocal 'x' found

Re-bind "x" to 2 in the first non-local frame of the current environment in which it is bound.

class ComplexRI: def __init__(self, real, imag): self.real = real self.imag = imag @property def magnitude(self): return (self.real ** 2 + self.imag ** 2) ** 0.5 @property def angle(self): return atan2(self.imag, self.real) def __repr__(self): return 'ComplexRI({0}, {1})'.format(self.real, self.imag)

math.atan2(y,x): Angle between x-axis and the point (x,y)

Property decorator: "Call this function on attribute look-up"

Type dispatching: Look up a cross-type implementation of an operation based on the types of its argumentsData-directed programming: Look up a cross-type implementation based on both the operator and types of its argumentsType coercion: Look up a function for converting one type to another, then apply a type-specific implementation.

>>> z = ComplexRI(-1, 0)>>> (z.real, z.imag)(-1, 0)>>> z.magnitude1>>> z.angle3.141592653589793

User-defined complex type:

CS 61A Midterm 2 Study Guide – Page 2

A class statement creates a new class and binds that class to <name> in the first frame of the current environment.Statements in the <suite> create attributes of the class.As soon as an instance is created, it is passed to __init__, which is a class attribute called the constructor method.

class <name>: <suite>

The suite is executed when a class statement is evaluated.

When a class is called:

1.A new instance of that class is created:

2.The constructor __init__ of the class is called with the new object as its first argument (named self), along with any additional arguments provided in the call expression.

>>> a = Account('Jim')

class Account: def __init__(self, account_holder): self.balance = 0 self.holder = account_holder

>>> a = Account('Jim')>>> b = Account('Jack')

>>> a is aTrue>>> a is not bTrue

Every object that is an instance of a user-defined class has a unique identity:

Binding an object to a new name using assignment does not create a new object:

Identity testing is performed by "is" and "is not" operators:

>>> c = a>>> c is aTrue

Every call to Account creates a new Account instance. There is only one Account class.

All invoked methods have access to the object via the self parameter, and so they can all access and manipulate the object's state.

class Account: ...

def deposit(self, amount): self.balance = self.balance + amount return self.balance

>>> tom_account = Account('Tom')>>> tom_account.deposit(100)100

Dot notation automatically supplies the first argument to a method.

Invoked with one argument

Defined with two arguments

Assignment statements with a dot expression on their left-hand side affect attributes for the object of that dot expression• For an instance, then assignment sets an instance attribute• For a class, then assignment sets a class attribute

>>> jim_account = Account('Jim')>>> tom_account = Account('Tom')>>> tom_account.interest0.02>>> jim_account.interest0.02>>> Account.interest = 0.04>>> tom_account.interest0.04

>>> jim_account.interest = 0.08>>> jim_account.interest0.08>>> tom_account.interest0.04>>> Account.interest = 0.05>>> tom_account.interest0.05>>> jim_account.interest0.08

Objects receive messages via dot notation.Dot notation accesses attributes of the instance or its class.

<expression> . <name>The <expression> can be any valid Python expression.The <name> must be a simple name.Evaluates to the value of the attribute looked up by <name> in the object that is the value of the <expression>.

tom_account.deposit(10)

Dot expressionCall expression

To evaluate a dot expression:1.Evaluate the <expression> to the left of the dot, which

yields the object of the dot expression.2.<name> is matched against the instance attributes of that

object; if an attribute with that name exists, its value is returned.

3.If not, <name> is looked up in the class, which yields a class attribute value (see inheritance below).

4.That value is returned unless it is a function, in which case a bound method is returned instead.

0.05Account class attributes

interest: 0.02(withdraw, deposit, __init__)

0.04

balance: 0holder: 'Jim'

Instance attributes of jim_account

balance: 0holder: 'Tom'

Instance attributes of tom_account

interest: 0.08

class CheckingAccount(Account): """A bank account that charges for withdrawals.""" withdraw_fee = 1 interest = 0.01 def withdraw(self, amount): return Account.withdraw(self, amount + self.withdraw_fee)

Inheritance: To look up a name in a class.1. If it names an attribute in the class, return its value.2. Otherwise, look up the name in the base class, if it exists.

>>> ch = CheckingAccount('Tom') # Calls Account.__init__>>> ch.interest # Found in CheckingAccount0.01>>> ch.deposit(20) # Found in Account20>>> ch.withdraw(5) # Found in CheckingAccount14

class Account: def __init__(self, account_holder): self.balance = 0 self.holder = account_holder def deposit(self, amount): self.balance = self.balance + amount return self.balance def withdraw(self, amount): if amount > self.balance: return 'Insufficient funds' self.balance = self.balance - amount return self.balance

class SavingsAccount(Account): deposit_fee = 2 def deposit(self, amount): return Account.deposit(self, amount - self.deposit_fee)

class AsSeenOnTVAccount(CheckingAccount, SavingsAccount): def __init__(self, account_holder): self.holder = account_holder self.balance = 1 # A free dollar!

class Rlist: class EmptyList: def __len__(self): return 0 empty = EmptyList() def __init__(self, first, rest=empty): assert type(rest) is Rlist or rest is Rlist.empty self.first = first self.rest = rest def __getitem__(self, index): if index == 0: return self.first else: return self.rest[index-1] def __len__(self): return 1 + len(self.rest) def __repr__(self): rest = '' if self.rest is not Rlist.empty: rest = ', ' + repr(self.rest) return 'Rlist({0}{1})'.format(self.first, rest)

Yes, this call is recursive

There's the base case!

def extend_rlist(s1, s2): if s1 is Rlist.empty: return s2 return Rlist(s1.first, extend_rlist(s1.rest, s2))

class Tree: def __init__(self, entry, left=None, right=None): self.entry = entry self.left = left self.right = right

def memo(f): cache = {} def memoized(n): if n not in cache: cache[n] = f(n) return cache[n] return memoized

def sum_entries(t): if t is None: return 0 else: return t.entry + sum_entries(t.left) + sum_entries(t.right)

12

3

Rlist(1, Rlist(2, Rlist(3)))

2

1 1

0 1

Tree(2, Tree(1), Tree(1, Tree(0), Tree(1)))left and right are

Trees or None

R(n) = �(f(n))

k1 · f(n) � R(n) � k2 · f(n)

n: size of the problemR(n): Measurement of some resource

means that there are positive constants k1 and k2 such that

for sufficiently large values of n.

�(bn)

�(n)

�(log n)

�(1)

⇥(n2)

Exponential growth! Incrementing the problem scales R(n) by a factor.

Linear growth.

Logarithmic growth.Doubling the problem only increments R(n).

Constant.

Quadratic growth. Incrementing n increases R(n) by the problem size n.

Resources scale with the problem size.

Independent of problem size.

5

3

1 7

9

11

8

7

9

11

8 7 8

Right! Left! Right!

None None

8None

Stop!

Tree set: A set is a Tree. Each entry is:• Larger than all entries in its left branch, and• Smaller than all entries in its right branch