2023-Fall-Final 2
2023-Fall-Final 2
This 150-minute exam has 8 questions worth a total of 100 points. Scan the whole test before
starting. Budget your time wisely. Use the back of the pages if you need more space. You may tear
the pages apart; we have a stapler at the front of the room.
It is a violation of the Academic Integrity Code to look at any exam other than your
own, look at any reference material, or otherwise give or receive unauthorized help.
You will be expected to write Python code on this exam. We recommend that you draw vertical
lines to make your indentation clear, as follows:
def foo():
if something:
do something
do more things
do something last
Unless you are explicitly directed otherwise, you may use anything you have learned in this course.
You may use the backside of each page for extra room for your answers. However, if you do this,
please indicate clearly on the page of the associated problem.
References
String Operations
Expression Description
List Operations
Expression Description
Dictionary Operations
Expression Description
Page 2
Last Name: First: Netid:
(b) [3 points] Execute the four statements below. What is printed out? Explain your answer.
>>> a = [1,2]
>>> b = a[:]
>>> print (a == b)
>>> print (a is b)
(c) [3 points] What are the names of the two sorting algorithms that take n2 steps to complete?
What is the difference between them?
Page 3
Last Name: First: Netid:
(b) [4 points] Given the function below, enforce its preconditions (but do not implement it)
according to the specification. You should not use assert statements. Instead, write
code that produces the errors specified. You may use the function above as a helper.
def flatten(value):
"""Returns a CSV table flattened into a list of strings.
Page 4
Last Name: First: Netid:
(c) [4 points] Implement the function below. You may use any of the previous two function
as helpers. However, you may not use if-statements; you must use try-except.
def flatten_if_safe(value):
"""Returns the flattened list of value IF it is a CSV table.
If value is a list but not a CSV table, this function returns the empty
list. If it is not a list, this function returns None.
Precond: value can be ANYTHING"""
Suppose we have a list a = [5,4], together with the recursive function reverse shown below.
1 def reverse(seq):
id1
2 """Returns the reverse of seq"""
3 right = seq[1:] a id1
4 if right == []: list
5 return seq
6 0 5
7 left = seq[:1] 1 4
8 return reverse(right)+left
On the next two pages, diagram the evolution of the function call
b = reverse(a)
Diagram the state of the entire call stack for the function reverse when it starts, for each line
executed, and when the frame is erased. If any other functions are called, you should do this
for them as well (at the appropriate time). This will require a total of ten diagrams.
You should draw also the state of global space and the heap at each step. You can ignore the
folders for the function definitions. Only draw folders for lists or objects. To help conserve
time, you are allowed (and encouraged) to write “unchanged” if no changes were made to
either a call frame, the global space, or the heap. In the case of the heap, you can point out
that individual folder ids are unchanged.
Page 5
Last Name: First: Netid:
id2
id2
Page 6
Last Name: First: Netid:
id2
id2
id2
10
Page 7
Last Name: First: Netid:
ellipse = GEllipse(x=0,y=0,width=20,height=20,fillcolor='red')
Implementing mouse control is too messy for an exam, so we control the slider with an additional
attribute called _value. This attribute must be in sync with the knob. When it changes, the
knob moves (we will not worry about what to do when the knob moves first). This is expressed
by the specification on the next page.
With this in mind, implement this class on the next page. We have provided the specifications
for the methods __init__ and draw. You should fill in the missing details to meet these
specifications. In addition, you must add the getters and setters (where appropriate) for the new
attributes. Remember that setters must have preconditions to enforce the attribute invariants.
All type-based preconditions should be enforced by isinstance.
Hint: The attributes in GPath and GEllipse work like they do in Assignment 7, and have
invisible setters and getters. Therefore, you never have to enforce the invariants for these
attributes. You only need to worry about your new attributes: _knob and _value.
Page 8
Last Name: First: Netid:
class GSlider(GPath):
"""A class representing a graphical slider."""
# MUTABLE ATTRIBUTES:
# Invariant: _value is a float in 0 to 1, inclusive
# IMMUTABLE ATTRIBUTES:
# Invariant: _knob is a GEllipse
# ADDITIONAL INVARIANT
# If the slider path is from (x0,y0) to (x1,y1), the _knob is located at
# x = (x1-x0)*_value+x0, y =(y1-y0)*_value+y0
# DEFINE GETTERS/SETTERS AS APPROPRIATE. SPECIFICATIONS NOT NEEDED.
The initial value is 0. The slider line is black, which is the default color
(no need to set it). The knob has the given radius and a fillcolor of 'blue'.
Precond: x0, y0, x1, and y1 (in that order) are all ints
Precond: radius is an int >= 1 (OPTIONAL; default 10)"""
Page 9
Last Name: First: Netid:
The function rot_ccw below takes an upper triangular list and rotates it counter-clockwise.
This is similar to transpose (shown in class) where rows are swapped with columns. But the
rows in the rotated copy are arranged in reverse order from the columns in the original.
For example, rot_ccw takes the upper triangular matrix above on the left and returns the lower
triangular matrix on the right. With this explanation, implement the function below.
Hint: Do not think about looping over the original triangular list. That will confuse you.
Think about looping over the list you are returning (the one you are building), and then figure
out how to get the elements you want from the original list.
def rot_ccw(tri):
"""Returns a new lower triangular list from rotating tri counter-clockwise
Page 10
Last Name: First: Netid:
def pascal_level(n):
"""Returns: the nth level of the pascal triangle
Page 11
Last Name: First: Netid:
(b) [9 points]
def fibfrom(n):
"""Generates the Fibonnacci sequence, starting with the nth value.
The Fibonnaci sequence starts with 1 and 1, and adds the previous two values
to get the next value. This sequence is infinite, so the generator is too.
Ex: fibfrom(0) generates 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
Ex: fibfrom(4) generates 5, 8, 13, 21, 34, ...
Precond: n >= 0 is an int"""
# HINT: You do not need recursion for this. Do not use recursion.
Page 12