This document contains the instructions for the week 2 CSC148H/A48H lab. To earn your lab mark, you must actively participate in the lab. We mark you in order to ensure a serious attempt at learning, not to make careful critical judgments on your work.
Here are the activities for this lab:
You'll be spending lots of hours with your TA and fellow inmates, so you'll start by getting to know them. Your TA will get you going on this.
Sit down with your partner. The rest of these instructions call you two s1 and s2. Pick which one is which.
Repeat the following set of instructions twice, once for s1 and once for s2.
Start your browser, go to the CSC148H/A48H web site, and select the "Labs" link. Find the Week 2 entry and open it. This will allow you to click on links and download files for the lab.
On StG, we will sometimes email information to everyone's CSC148H account. Unless this will be your primary email account, you must set up email forwarding. Do this now.
Later, at home, check to see that you set up forwarding properly, by sending mail to yourself and seeing if it appears at the right destination account. Too often, we send messages such as assignment marks to students, only to find their addresses are wrong -- and we can't fix them. Please check your forwarding!
Brief instructions, in case the web reference isn't enough:
Create a file called ".forward
" -- don't forget the period
at the beginning of the name -- in your home directory, and put your
forwarding address in the file. You can edit your .forward
file in Wing. If you see someone having trouble, please help them. Some
of the class are new to the computer labs -- please make them feel
welcome!
In this lab, you'll be working in the pair programming model. Obviously, two programmers are involved, and we call these two people the driver and the navigator. Here are the definitions of the two roles:
And here is the most important rule for this lab:
Throughout the lab, you'll be switching back and forth between the driver and navigator roles. s1 will be the first driver, so s1 should now log in again.
stack.py
.
driver.py
, and add code to
it so that it:
Run your program. When you're done, show your TA.
Switch roles: now, s2 drives and s1 navigates.
driver.py
to read in a list of lines from
standard input, until the string "end"
is typed, and put
each line into a Stack. Remember that a "read and process
loop" looks like this:
Read a lineYou can read a line with
while not done:
Process the line that was read
Read the next line
raw_input("Type a string: ")
. Run your program. When you're done, show your TA.
Switch roles again: s1 drives and s2 navigates.
driver.py
to print the lines
you stored in the stack.
Run your program. When you're done, show your TA.
A queue is another ADT much like a stack, except that items are added at the rear and removed from the front. (Like a lineup at a bank.) Here are the standard operations:
enqueue(o)
Add a new item to the rear of the
queue. dequeue()
Remove and return the front item. front()
Return the front item. isEmpty()
Test whether the queue is empty. size()
Return the number of items in the queue. Switch roles again: s2 drives and s1 navigates.
Save the file queue.py
, which
implements the Queue
ADT. Modify the implementation so
that it also supports the following method:
remove(o)
Remove the first occurrence of object o
from the queue if it exists
Here is a test_queue.py file containing nose unit tests; modify it so that it tests the new method that you implemented. When you have done this and all the tests pass, show your TA.
In lecture, we found that using index 0 as the top of a stack was inefficient. The same problem happens with our queue implementation: every time we dequeue we must shift everything over. You can see some numbers by running time_queue.py, where we put a bunch of items into a queue and then enqueue and dequeue 20000 items. Get out a piece of paper and spend some time with your partner brainstorming possible solutions to this problem. Draw a list, and think about keeping front and rear indices. Don't worry if you can't come up with a solution, but do spend some time arguing.
Switch roles again: s1 drives and s2 navigates.
A priority queue is
another ADT that is slightly different from a regular queue ADT. Instead of removing items
in the order in which they were added to the queue, items are removed
in
order of their priority. Here are the operations:
insert(o)
Add a new item to the queueextractMin()
Remove and return the item with highest
prioritymin()
Return the item with highest priorityisEmpty()
Test whether the queue is emptysize()
Return the number of items in the queuePriorityQueue
ADT using a heap.
Heaps are a topic
that we will cover later in the course. At this point, you do not need
to actually
understand the details of how the PriorityQueue
in
pqueue.py works, but you do need to be able to use
it.Event
class that has an associated timestamp. The
timestamp is simply an integer that represents the number of units of
time that have elapsed from some arbitrary starting point. Whenever you
create a new instance of an Event
, you pass it a
timestamp in the constructor. driver.py
so that there are two instances of
a priority queue and no stack. Also modify driver.py
so
that it expects input lines to contain integers (except for the "end"
line):
i = int(line)
Event
with that integer as the timestamp, and insert the event into the
second instance of the priority queue. Event
class the way there is for
integers. In order to fix this, add the following method to the
Event
class:def __cmp__(self, other):
if self.timestamp < other.timestamp:
return -1
elif self.timestamp > other.timestamp:
return 1
else:
return 0
Event
class). This information is provided by the __cmp__
method of the class. Suppose e1
and e2
are
instances of the Event class. Whenever an expression of the form "e1
< e2
" or "e1 > e2
" appears, Python
makes the call e1.__cmp__(e2)
to help determine the
expression's truth or falsity. (If the expression were "e2 < e1
"
or "e2 > e1
", the call would be e2.__cmp__(e1)
instead.
Python behaves analagously for the other comparison operators.)
The return value from __cmp__
tells Python the relative
ordering of the two objects. In particular, if __cmp__
returns a negative number, then the self
object is less
than the other
object, and if return value is positive,
then the self
object is greater than the other
object. As you can see in our above implementation of __cmp__
,
whenever the self
object has a smaller timestamp than the
other
object, a negative number is returned, indicating
that self
is less than other
. __cmp__
so that 1 is returned in the first case,
and -1 in the second case, and try running your program again. What has
happened? Can you explain why such a small change has made such a
dramatic difference?