import algolab
import sys
sys.path.append('past-exams/2017-01-13-midterm/solutions')
algolab.init()
If you don't ship or you don't pass this midterm, you lose also the theory midterm.
Log into your computer in exam mode, it should start Ubuntu
There won't be any internet access. You will only be able to access:
One extra point can be earned by writing stylish code. You got style if you:
avoid convoluted code like i.e.
if x > 5:
return True
else:
return False
when you could write just
return x > 5
%%HTML
<p class="algolab-warn">
!!!!!!!!! WARNING !!!!!!!!!
<br/>
<br/>
!!!!!!!!! **ONLY** IMPLEMENTATIONS OF THE PROVIDED FUNCTION SIGNATURES WILL BE EVALUATED !!!!!!!!! <br/>
</p>
For example, if you are given to implement:
def cool_fun(x):
raise Exception("TODO implement me")
and you ship this code:
def cool_fun_non_working_trial(x):
# do some absurdity
def cool_fun_a_perfectly_working_trial(x):
# a super fast, correct and stylish implementation
def cool_fun(x):
raise Exception("TODO implement me")
We will assess only the latter one cool_fun(x)
, and conclude it doesn't work at all :P !!!!!!!
Still, you are allowed to define any extra helper function you might need. If your cool_fun(x)
implementation calls some other function you defined like my_helper
here, it is ok:
def my_helper(y,z):
# do something useful
def cool_fun(x):
my_helper(x,5)
# this will get ignored:
def some_trial(x):
# do some absurdity
In /usr/local
you should find somewhere a file named sciprog-midterm-17-01-13.zip
. Download it and extract it in a new folder on your desktop. The content should be like this:
|- docs
|- algolab-17-01-13
|- exercise1.py
|- exercise2.py
|- exercise3.py
|- exercise4.py
Under docs/
folder you will find the slides and Python documentation.
2) Now, take the folder algolab-17-01-13
and copy it to /var/exam
.
Rename it to algolab-17-01-13-midterm-FIRSTNAME-LASTNAME-IDNUMBER
like algolab-17-01-13-john-doe-432432
From now on, you will be editing the files in that folder. At the end of the exam, that is what will be evaluated.
3) Edit the files following the instructions in this worksheet for each exercise.
%%HTML
<p class="algolab-warn">
WARNING: <i>DON'T</i> modify function signatures! Just provide the implementation.
</p>
<p class="algolab-warn">
WARNING: <i>DON'T</i> change the existing test methods, just add new ones !!! You can add as many as you want.
</p>
<p class="algolab-warn">
WARNING: <i>DON'T</i> create other files. If you still do it, they won't be evaluated.
</p>
<p class="algolab-important">
IMPORTANT: Pay close attention to the comments of the functions.
</p>
<p class="algolab-important">
IMPORTANT: if you need to print some debugging information, you <i>are allowed</i> to put extra <code>print</code>
statements in the function bodies.
</p>
<p class="algolab-warn">
WARNING: even if <code>print</code> statements are allowed, be careful with prints that might
break your function, i.e. avoid stuff like this: <code> print 1/0 </code>
</p>
3) Every exercise should take max 25 mins. If it takes longer, leave it and try another exercise.
%%HTML
<p class="algolab-warn">
WARNING: MAKE SURE ALL EXERCISE FILES AT LEAST COMPILE !!! <br/> 10 MINS BEFORE THE END OF THE EXAM I WILL ASK YOU TO MAKE
SURE OF THIS AND TO DO A FINAL CLEAN UP OF THE CODE:
</p>
Quick sort is a widely used sorting algorithm and in this exercise you will implement it following the pseudo code.
IMPORTANT: Array A
in the pseudo code has indexes starting from zero included
IMPORTANT: The functions pivot
and quicksort
operate an a subarray that goes from indeces first
included and last
included
Start editing the file exercise1.py
:
Implement swap
:
def swap(A, x, y):
"""
In the array A, swaps the elements at indeces x and y.
"""
raise Exception("TODO IMPLEMENT ME!")
Once done, running this will run only the tests in SwapTest
class and hopefully they will pass.
Notice that exercise1
is followed by a dot and test class name: .SwapTest
python -m unittest exercise1.SwapTest
Implement pivot
method:
def pivot(A, first, last):
""" Modifies in-place the slice of the array A with indeces between first included
and last included. Returns the new pivot index.
"""
raise Exception("TODO IMPLEMENT ME!")
You can run tests only for pivot
with this command:
python -m unittest exercise1.PivotTest
Implement quicksort
and qs
method:
def quicksort(A, first, last):
"""
Sorts in-place the slice of the array A with indeces between first included
and last included.
"""
raise Exception("TODO IMPLEMENT ME !")
def qs(A):
"""
Sorts in-place the array A by calling quicksort function on the full array.
"""
raise Exception("TODO IMPLEMENT ME !")
You can run tests only for both quicksort
and qs
with this command:
python -m unittest exercise1.QuicksortTest
In class you implemented a CappedStack
that had a fixed cap
. In this exercise, you will implement a way to change the cap
after that a stack instance has been created.
NOTE: On some condition, you will be requested to raise IndexError
. To do so, just write:
raise IndexError("Error!")
Proceed with the following point and start editing the file exercise2.py
Implement the peekn
method:
def peekn(self, n):
"""
Returns a list with the n top elements, in the order in which they
were pushed. For example, if the stack is the following:
e
d
c
b
a
peekn(3) will return the list ['c','d','e']
If there aren't enough element to peek, raises IndexError
If n is negative, raises an IndexError
"""
raise Exception("TODO IMPLEMENT ME!")
Implement the popn
method:
def popn(self, n):
""" Pops the top n elements, and return them as a list, in the order in
which they where pushed. For example, with the following stack:
e
d
c
b
a
popn(3)
will give back ['c','d','e'], and stack will become:
b
a
If there aren't enough element to pop, raises an IndexError
If n is negative, raises an IndexError
"""
Implement the set_cap
method:
def set_cap(self, cap):
""" Sets the cap value to the provided cap.
If the cap is less then the stack size, all the elements above
the cap are removed from the stack.
If cap < 1, raises an IndexError
Does *not* return anything!
For example, with the following stack, and cap at position 7:
cap -> 7
6
5 e
4 d
3 c
2 b
1 a
calling method set_cap(3) will change the stack to this:
cap -> 3 c
2 b
1 a
"""
raise Exception("TODO IMPLEMENT ME")
Let's work on UnorderedList
, which is a monodirectional linked list.
Start editing the file exercise3.py
Implement this method:
def occurrences(self, item):
"""
Returns the number of occurrences of item in the list.
"""
Examples:
from exercise3_solution import *
ul = UnorderedList()
ul.add('a')
ul.add('c')
ul.add('b')
ul.add('a')
print ul
print ul.occurrences('a')
print ul.occurrences('c')
print ul.occurrences('z')
Implement this method in UnorderedList
class:
def shrink(self):
"""
Removes from this UnorderedList all nodes at odd indeces (1, 3, 5, ...),
supposing that the first node has index zero, the second node
has index one, and so on.
So if the UnorderedList is
'a','b','c','d','e'
a call to shrink will transform the UnorderedList into
'a','c','e'
Must execute in O(n) where 'n' is the length of the list.
Does *not* return anything.
"""
raise Exception("TODO IMPLEMENT ME!")
ul = UnorderedList()
ul.add('e')
ul.add('d')
ul.add('c')
ul.add('b')
ul.add('a')
print ul
ul.shrink()
print ul
In these exercises with a tree, you will be visiting a generic tree in various ways.
The method zig
must return as output a list of data
of the root and all the nodes in the chain of child
attributes. Basically, you just have to follow the red lines and gather data
in a list, until there are no more red lines to follow. For example, in the labeled tree in the image, these would be the results of calling zig
on various nodes:
a
: ['a','b', 'e']
b
: ['b', 'e']
c
: ['c', 'g']
h
: ['h']
q
: ['h']
This function is quite similar to zig
, but this time it gathers data going right, along the sibling
arrows. For example, in the labeled tree in the image, these would be the results of calling zag
on various nodes:
a
: ['a']
b
: ['b', 'c', 'd']
o
: ['o', 'p']
If you arrived so far and some unit test for previous exercises (1,2,3,4) are still failing, it's probably more convenient to try to fix it. On the other hand, if everything is working fine, you should proceed with this slightly challanging exercise!
As you are surely thinking, zig
and zag
alone are boring. So let's mix the concepts, and go zigzaging. This time you will write a function zigzag
, that first zigs collecting data
along the child vertical red chain as much as it can. Then, if the last node links to at least a sibling, the method continues to collect data along the siblings horizontal chain as much as it can. At this point, if it finds a child, it goes zigging again along the child vertical red chain as much as it can, and then horizontal zaging, and so on. It continues zig-zaging like this until it reaches a node that has no child nor sibling: when this happens returns the list of data found so far. For example, these would be the results of calling zigzag
on various nodes:
a
: ['a', 'b', 'e', 'f', 'o']
c
: ['c', 'g', 'h', 'i', 'q']
NOTE: if node h
had a child z
, the process would still proceed to i
d
: ['d', 'm', 'n']
o
: ['o', 'p']
n
: ['n']