Py Exercise
Py Exercise
1 Ge ng Started 1
Self-Review Ques ons 1
Programming Exercises 3
Challenges 6
2 The Fundamentals 9
Self-Review Ques ons 9
Programming Exercises 10
Challenges 15
4 Structuring State 27
Self-Review Ques ons 27
Programming Exercises 29
Challenges 33
6 Classy Objects 45
Self-Review Ques ons 45
Programming Exercises 47
Challenges 51
ii Contents
7 Inheri ng Class 55
Self-Review Ques ons 55
Programming Exercises 56 Challenges
60
13 PyGames 99
Self-Review Ques ons 99
Programming Exercises 100
Challenges 101
Ge ng Started
Because the Python system evaluates the expression 4 + 9 which means adding 4 to 9
giving the result 13 which is the printed out.
Self-review 1.2 Why is the following the case – rather than the result being 13?
>>> print "4 + 9"
4+9
>>>
1
Because "4+9" is a string and so it is printed as is, there is no expression to be evaluated.
Self-review 1.3 Why does the expression 2 + 3 * 4 result in the value 14 and not the value
24?
Because the * operator has higher precedence than the operator +. The 3 * 4
subexpression is evaluated first giving 12 and then the expression 2 + 12 is evaluated
resul ng in 14.
Self-review 1.10 The Turtle module provides a func on to draw circles. If this func on
was not available, what algorithm would you use to draw a circle?
Draw a large number of very short straight lines changing the direc on of travel by 360°
divided by the number of lines. So if the number is 3 we have a triangle. If the number is
4 we have a square. If the number is 5 we have a pentagon, with 6 a hexagon. If we have
100 sides then for a small ‘circle’ it may not be no ceable that the lines are straight.
turtle.goto = goto(*args)
Go to the given point.
goto(x, y) go to
point (x, y)
Programming Exercises
3
goto((x, y)) go
to point (x, y)
Example:
>>> turtle.posi on()
[0.0, 0.0]
>>> turtle.goto(50, -45)
>>> turtle.posi on()
[50.0, -45.0]
Programming Exercises
Exercise 1.1 Es mate the size of your computer screen by impor ng the Turtle module
and causing the turtle to move 1 pixel (though you may want to try 10
pixels!).
Using the program:
import turtle
Exercise 1.2 Experiment with the ‘square spiral’ program, varying the lengths of
various lines. Which values make spirals and which do not? Which values make the
nicest-looking spiral?
import turtle
4 Ge ng Started
turtle.forward ( 70 )
turtle.le ( 135 )
turtle.forward ( 50 )
turtle.le ( 90 )
turtle.forward ( 50 )
# Prompt to stop the program from termina ng and hence the display from disappearing.
Exercise 1.4 Write a program to draw a red circle, then a yellow circle underneath it and
a green circle underneath that. The result should look something like:
import turtle
Exercise 1.5 Amend your program from the previous ques on so that the circles are filled
and hence the result looks something like:
Programming Exercises
import turtle
5
turtle.up ( ) turtle.goto ( 0 , 35 ) turtle.down ( )
turtle.color ( ’red’ ) turtle.fill ( 1 ) turtle.circle ( 20 )
turtle.fill ( 0 ) turtle.up ( ) turtle.goto ( 0 , -20 )
turtle.down ( ) turtle.color ( ’yellow’ ) turtle.fill ( 1 )
turtle.circle ( 20 ) turtle.fill ( 0 ) turtle.up ( )
turtle.goto ( 0 , -75 ) turtle.down ( ) turtle.color (
’green’ ) turtle.fill ( 1 ) turtle.circle ( 20 ) turtle.fill ( 0 )
raw_input ( ’Press return to terminate the program: ’
)
Exercise 1.6 Write a program to draw a regular hexagon. The result should look something like:
Hint: Regular hexagons have six sides, of equal length, which meet at an internal
angle of 120°.
import turtle
Challenges
import turtle
turtle.forward ( 10 )
turtle.le ( 120 )
turtle.forward ( 15 )
turtle.le ( 120 )
turtle.forward ( 20 )
turtle.le ( 120 )
turtle.forward ( 25 )
turtle.le ( 120 )
turtle.forward ( 30 )
turtle.le ( 120 )
turtle.forward ( 35 )
turtle.le ( 120 )
turtle.forward ( 40 )
turtle.le ( 120 )
turtle.forward ( 45 )
Challenges
Hint: You may want to start by doing some trigonometry to sort out all the
angles and lengths. Pythagoras’ Theorem will almost certainly come
in useful: Pythagoras’ Theorem states that for a right-angled
triangle:
hypotenuse =px2+y2
where hypotenuse is the longest side of the triangle and x and y are
the lengths of the other two sides.
7
Hint: To find the square root of a number in Python, you need to import the
module math and call the func on math.sqrt: to find the square root
of 2, you import the math module, then write math.sqrt(2).
#! /usr/bin/env python
import turtle
import math #
Assume the house
body is a square
and the roof is a
right-angled
triangle (half a
square).
We
# can then get the various diagonals using Pythogoras’ Theorem with all angles being
mul ples # of 45.
# It seems almost totally unreasonable not to use variables to solve this problem.
sideLength = 40
halfDiagonalLength = 0.5 * math.sqrt ( 2 * ( sideLength ** 2 ) )
turtle.le ( 90 ) #
turtle.forward ( sideLength )
turtle.right ( 135 ) turtle.forward (
halfDiagonalLength ) turtle.right (
90 ) turtle.forward (
halfDiagonalLength ) turtle.le (
135 ) turtle.forward ( sideLength )
turtle.le ( 135 ) turtle.forward (
halfDiagonalLength ) turtle.right (
90 ) turtle.forward (
halfDiagonalLength ) turtle.le (
135 ) turtle.forward ( sideLength )
turtle.right ( 135 ) turtle.forward (
halfDiagonalLength ) turtle.right (
90 ) turtle.forward (
halfDiagonalLength ) turtle.right (
45 ) turtle.forward ( sideLength )
# Prompt to stop the program from termina ng and hence the display from disappearing.
Self-review 2.1 What are the types of the following literals? 1, 1., 1.0, ’’1’’, ’’1.’’,
’’1.0’’, ’1’, ’1.’, 100000000000000000, 100000000000000000., 100000000000000000.0.
int, float, float, str, str, str, str, str, long, float, float.
Self-review 2.2 Explain the difference between the following two statements:
print 12
print "12"
The first print the integer literal 12, the second prints the string comprising the character 1 followed
by the character 2.
The literals are: 3, ’1’, 2, "dog", ’, went to mow a meadow.’, ’man’, "and his", ",", "and his".
Self-review 2.5 What are the types of the variables a, b, c, d, e, f, g in the above program?
int, str, int, int, str, str, str
The Fundamentals
Self-review 2.6 Is there a difference between the type of the expressions "python" and
’python’?
8. the 4/2 is evaluated first then the le addi on 4+2, then the right addi on 6+2.
Self-review 2.8 Add brackets as needed to the above expression to make the answer:
a. 2
b. 5
c. 6
1. ( 4 + 4 ) / ( 2 + 2 )
2. 4 + ( 4 / ( 2 + 2 ) )
3. ( 4 + 4 ) / 2 + 2
Self-review 2.10 What is the difference between the expressions c = 299792458 and c =
2.99792458 * 10 ** 8?
In the first c is of type int, in the second, c is of type float. The value represented is the same.
Self-review 2.11 What does this expression n < 140 mean? I.e. what test is undertaken and what
is the value and type of the result?
It tests whether the value of the variable n is less than the literal 140 and delivers True if it is
and False if it is not. The result of the expression if of type bool.
Self-review 2.12 What is the value of the variable val a er the execu ng the expression val = 1 /
2? What is the type of val?
Self-review 2.13 What is the value of the variable val a er the execu ng the expression val = 1 /
2.0? What is the type of val?
Self-review 2.14 What are the possible values contained in a variable of type bool?
Programming Exercises
import turtle
scale = 4
## Le er A
turtle.down ( )
# Point upwards to begin
turtle.le ( turtle.heading ( ) + 90
) turtle.right ( 20 ) turtle.forward (
10 * scale ) turtle.right ( 70 )
turtle.forward ( 1 * scale )
turtle.right ( 70 ) turtle.forward (
10 * scale ) turtle.backward ( 5 *
scale ) turtle.right ( 90 + 20 )
turtle.forward ( 5 * scale )
#Move to right of le er and over 1 *
scale turtle.up ( ) turtle.backward ( 5 *
scale ) turtle.le ( 110 ) turtle.forward (
5 * scale ) turtle.le ( 70 ) turtle.forward
( 1 * scale )
## Le er B turtle.down
()
# Point upwards to begin
turtle.le ( turtle.heading ( ) + 90
) turtle.forward ( 10 * scale )
turtle.right ( 90 ) turtle.forward (
4 * scale ) turtle.right ( 90 )
turtle.forward ( 4 * scale )
turtle.le ( 90 ) turtle.backward (
1 * scale ) turtle.forward ( 2 *
scale ) turtle.right ( 90 )
turtle.forward ( 6 * scale )
turtle.right ( 90 ) turtle.forward (
5 * scale ) # Move to right of le er
turtle.up ( ) turtle.right ( 180 )
turtle.forward ( 6 * scale )
## Le er C
turtle.down ( )
# Point upwards to begin
turtle.le ( turtle.heading ( ) + 90
) turtle.forward ( 10 * scale )
turtle.right ( 90 ) turtle.forward (
4 * scale ) turtle.backward ( 4 *
scale ) turtle.le ( 90 )
turtle.backward ( 10 * scale
) turtle.right ( 90 )
turtle.forward ( 4 * scale ) #
Move to right of le er
The Fundamentals
turtle.up ( ) turtle.forward (
1 * scale )
# Pause
raw_input ( "Press any key to end." )
The code for wri ng each individual le er is fairly easy to spot, because of
the comments. There’s a much easier way to divide this code up though:
func ons. The exercise then is to:
1. Modify the code so that each le er is drawn by a func on: drawA ( ) for the
le er A, for example.
2. Add the le ers “D” and “E” as func ons.
3. Amend the code to display the word “DECADE” rather than “ABCDE”.
Exercise 2.2 Rewrite your answer to Exercise 1.4 (three colored circles one above the other)
using a func on.
import turtle
def drawAtWithColor ( x , y , c ) :
turtle.up ( )
turtle.goto ( x , y )
turtle.down ( )
turtle.color ( c )
turtle.circle ( 20 )
Exercise 2.3 Rewrite your answer to Exercise 1.5 (three colored, filled circles one above the
other) using a func on.
Programming Exercises
13
Hint: The answer should be a trivial extension to the answer of the previous ques on.
import turtle
def drawAtWithColor ( x , y , c ) :
turtle.up ( )
turtle.goto ( x , y )
turtle.down ( )
turtle.color ( c )
turtle.fill ( 1 )
turtle.circle ( 20 )
turtle.fill ( 0 )
Exercise 2.4 Rewrite your answer to ques on Exercise 1.6 (drawing a hexagon) using
itera on. import turtle
Exercise 2.5 Extend your answer to the previous ques on so that the number of sides to
draw is a parameter – this is a programming solu on for Selfreview 1.10.
How many sides do you need before it looks like a circle?
Experiment indicates that on a 1280×1024, 90dpi screen anything over about 20 sides cannot
easily be dis nguished from an actual circle.
Exercise 2.6 Rewrite your answer to Challenge 1.1 using a func on.
import turtle
length = 10
The Fundamentals
def drawPair ( ) : global
length turtle.forward (
length ) length += 5
turtle.le ( 120 )
turtle.forward ( length )
length += 5
turtle.le ( 120 )
for i in range ( 10 ) :
drawPair ( ) raw_input ( ’Press return to
import turtle
def setPosi on ( x , y ) :
turtle.up ( )
turtle.goto ( x , y )
turtle.down ( )
sides = 3
length = 5
result is:
i.e. it draws a triangle with circles along its edges. The inten on was that
modifying the variable sides would allow you to draw a square (by se ng it
to 4), a pentagon (se ng it to 5) and so on. This doesn’t currently work,
however. The programmer clearly became distracted and le the program
half finished. Your job is to make the code work as intended.
Hint: Remember that for any regular polygon, the external angles always add
up to 360. If they didn’t, it would either not be closed or it would
overlap, or it would not be regular!
Challenges
Challenge 2.1 Go back and make sure you finish the programming exercise on crea ng
polygons surrounded by circles. If necessary modify the program so that
the drawing is undertaken by a func on with parameters for side length
and number of sides. Then add a further parameter to your func on that
allows the size of the circles to be
The Fundamentals
adjusted. Finally, write a program that asks the user to enter values for
side length, number of sides and size of circles – this is now a general
purpose regular-polygon-surrounded-by-circles generator. Not en rely
useful per se, but fun!
Challenge 2.2 Can you spot a way of making money given the exchange rates in the last
version of the currency conversion program? The trick is to write a
program to show how much you could lose or make by exchanging
between these currencies.
What stops people (as opposed to banks) exploi ng this for profit?
(If you are a bank, the opportuni es here are called currency arbitrage, but it is
a high-risk ac vity.)
Controlling the Flow
3
Self-review 3.1 The following expression is true when age is 21 and height is 120, or age is 21 and height is
140:
1. a or (b and c) not a
2. b and c or False
3. a and b or c or (b and a)
4. a == True or b == False
Self-review 3.3 ‘Nand’ is an operator that is false only when both of its operands are true. Python
doesn’t have a nand operator, so how can we write an expression that is equivalent
toA nand B?
Self-review 3.4 Under what condi ons would the following code sequences print ‘B’?
1. if thing1 > 10 :
print ’A’
else: print ’B’
2. if thing1 > 10 :
print ’A’
elif thing1 > 200 : print ’B’
3. if thing1 > 10 :
print ’A’
if thing1 > 200 : print ’B’
4. if thing1 > 10 and thing1 < 10 :
print ’A’
else: print ’B’
Controlling the Flow
Self-review 3.5 How many mes will Python execute the code inside the following
while loops? You should answer the ques on without using the interpreter! Jus fy your
answers.
1. i=0
while i < 0 and i > 2 :
print "s ll going ..." i = i+1
2. i = 25
while i < 100 :
print "s ll going ..." i = i - 1
3. i=1
while i < 10000 and i > 0 and 1 : print "s ll going ..."
i=2*i
4. i=1
while i < 10000 and i > 0 and 0 : print "s ll going ..."
i=2*i
6. i=1
while i < 2048 and i > 0 : print "s ll going ..."
i=2*i
7. for i in [ ] :
print "foobar!"
Self-review 3.6 What extra assert statement would be worth adding to the set of asser ons that test the
contains func on on page ?? and page ???
To ensure there is no problem if the string is the last le ers.
assert contains ( ’hellohello’ , ’ohello’ ) == True
Self-review 3.7 Explain the difference between the itera ve version of factorial on page ?? and the
following:
Self-Review Ques ons
def factorial ( x ) :
if x < 0 :
raise ValueError , ’Factorial not applicable to nega ve values.’
elif x == 0 : return
1
19
else :
value = 1 for i in range ( x
, 1 , -1 ) :
value *= i return
value
Self-review 3.8 Compare the first power func on (in Sec on ??) to the more efficient one
in Sec on ??. How many mul plica ons does each implementa on
make to evaluate power ( 3 , 5 )? Make sure you show your reasoning.
Self-review 3.9 Referring to the recursive func on for genera ng numbers in the
Fibonacci Sequence (page ??), how many calls to fibonacci are made to
evaluate fibonacci ( 5 )? Can you write down a general rule for how many
calls must be made to evaluate fibonacci ( n )?
1. range ( 1 ,100 )
2. range ( 1 , 50 , 2 )
3. range ( 1 , 25 , 3 )
4. range ( 10 , -10 , -2 )
Self-review 3.11 The following code contains the names a, b and c. What is the scope of each of
the them?
a = 10 for b in range ( 1
, 10 ) : c = b + 10 print c
Self-review 3.12 What does the following code do? How might it be used in a larger program?
print ’Menu:’ print ’1. Play
game’ print ’2. See high
score table’ print ’3. Exit’ i =
-1 while i < 1 or i > 3:
j = raw_input ( ’Enter choice: ’ )
try :
i = int ( j )
except :
con nue
Self-review 3.13 For the following recursive func on, label the base cases and recursive cases. What do
these func ons do?
def m ( a , b ) :
def mm ( a , b , c ) : if a == 0 : return c else : return mm
(a-1,b,c+b)
return mm ( a , b , 0 )
def d ( a , b ) :
Controlling the Flow
def dd ( a , b , c ) : if a < b : return c else : return dd ( a
-b,b,c+1)
return dd ( a , b , 0 )
Hint: You are almost certainly already familiar with these algorithms, just not in this form!
You might want to try working out what these func ons would return for some
simple input values.
Self-review 3.14 We are to write some assert statements of the form:
assert ( m ( ? , ? ) == ? ) and assert ( d ( ? , ? ) == ? ) to create tests for
the two func ons from Self-review 3.13. What
Self-review 3.15 What do the Python keywords break and con nue do?
Self-review 3.17 What do they keywords raise, try and except mean?
Programming Exercises
Exercise 3.1 Implement a recursive Python func on that returns the sum of the first n integers.
Exercise 3.2 Implement an itera ve Python func on that returns the sum of the first n integers.
Exercise 3.3 Implement an itera ve Python func on to generate numbers in the Fibonacci Sequence.
Programming Exercises
Exercise 3.4 While and for loops are equivalent: whatever you can do with one you can
do with the other. In the following programs, convert the following while
loops into for loops and the for loops into while loops. Of course, your new
loops should give the same results as the old ones!
4. char = ""
print "Press Tab Enter to stop and Enter to keep going ..."
itera on = 0 while not char == "\t" and not itera on >
99:
print "Keep going?"
char = raw_input()
itera on += 1
Exercise 3.5 Using books, the Web, or any other resource, find out what a logic gate is,
and, in par cular, what a half adder is. An output of the work should be a
table showing the inputs and outputs for a half adder.
Implement a half adder as a few lines of Python code. Write a test program
that shows that your implementa on works as expected. You should be able
to test that your code works for all possible input values.
Exercise 3.6 The following shows a Cesàro Fractal (also known as a Torn Square fractal). Write a
program to draw this figure.
Hint: The Cesàro Fractal is based on a square. Each line, if it is longer than the minimum line
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
# Even in Python 2.4.3, you s ll cannot have Unicode characters in func on names :-( import turtle
Controlling the Flow
def ini alize ( color = ’blue’ , smallest = 1.0 ) : ’’’Prepare to
draw CesÃaro Fractal’’’˘ turtle.clear ( ) turtle.up ( )
turtle.goto ( -100.0 , 100.0 ) turtle.setheading ( 0 )
turtle.color ( color ) turtle.down ( ) global
smallestLineLength smallestLineLength = smallest
cesaroLine ( overall )
if __name__ == ’__main__’ :
#ini alize ( ’brown’ , 100 ) ; cesaroLine ( 200 )
cesaroFractal ( 200.0 , 10.0 , ’brown’ )
raw_input ( ’Press any key to terminate’ )
Exercise 3.7 Self-review 3.13 contained recursive implementa ons of func ons m and d.
Write equivalent func ons that use itera on rather than recursion to
produce the same results
Exercise 3.8 Write a func on that capitalizes all the vowels in a string.
Hint: We have generally used indexing and the range func on when using for
loops. We can also use for loops for itera ng over the characters in a
string. For example:
for char in ’foobar’ :
print char
Hint: Look at the documenta on on strings: it has func ons one or more of
which are useful for this exercise. You might try using Python in
interac ve mode, impor ng the string module, and asking for help:
23
>>> import string >>> help(string) . . . or look up the string
module in the Python documenta on.
Exercise 3.9 Use the Turtle module and nested loops to draw the following shape:
import turtle
turtle.goto ( ( 0 , 100 ) )
turtle.goto ( ( 0 , 0 ) )
turtle.goto ( ( 100 , 0 ) )
turtle.goto ( ( 0 , 0 ) )
Enter to close.’ )
Exercise 3.10 Linux, Mac OS X, Solaris and other Unix-like systems have a command cal that, when
run without a parameter, prints out the calendar for the current month. For
example:
|> cal May 2007
Mo Tu We Th Fr Sa Su
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
|>
Use loops and nested loops to print out a similar table for this month. Try to make
sure that your columns line up correctly, like the example above!
Challenges
Find an algorithm for drawing a Dragon Curve and write a program to draw a figure
such as the one shown.
Hint: The star ng point for a Dragon Curve is a straight line, but you always have to
deal with two lines at a me. So this is not a simple recursion – more than one
recursive func on is needed.
# Even in Python 2.4.3, you s ll cannot have Unicode characters in func on names :-( import
Challenges
if __name__ == ’__main__’ :
#dragonCurve ( 2000.0 , 10.0 , ’purple’ )
#dragonCurve ( 4000.0 , 5.0 , ’purple’ )
dragonCurve ( 8000.0 , 2.5 , ’purple’ )
raw_input ( ’Press any key to terminate’ )
Challenge 3.2 One applica on area in which itera on and recursion are par cularly useful
is user interfaces – programs that directly interact with people. These
include websites, games, spreadsheets, and so on. For this challenge, you
will create a text-based user interface to the Python turtle. The idea
behind this is to let people use the turtle without having to learn Python
first.
As a start, here is some code that allows you to move the turtle around using the
keys a, s, w, and d on the keyboard:
import turtle
def turtle_interface ( ) :
"""Allow the user to control the turtle via the
keyboard.""" steps = 10 angle = 5 while True :
i = raw_input ( ) if i == ’w’ : turtle.forward ( steps ) elif i == ’s’ :
turtle.backward ( steps ) elif i == ’a’ : turtle.le ( angle ) elif i == ’d’ :
turtle.right ( angle ) elif i == ’q’ : break else : con nue
1. A func on to print out a menu before the user starts. This should explain which keys are used to
control the turtle. (Make sure that you keep the key map up to date as you add new
func onality to the program.)
2. User op ons to perform the following func ons:
(a) Clear the screen.
(b) Li the ’pen’ of the turtle off the page.
(c) Put the pen back down on the page.
(d) Change the width of the line that the turtle draws.
(e) Draw a circle. Be er s ll, let the user decide how big a radius the circle should have.
(f) Change the color of the turtle. Allow the user to choose from a small number of colors (say, red,
blue, green and black).
(You may well need to read through the documenta on for the Turtle module to implement these.)
Controlling the Flow
3. Undo capability. You will need to store the last key the user pressed and write some code (maybe in
a separate func on) to map keys onto their opposite ac ons. This might not be possible for some user
op ons (such as drawing a circle) but others should be straigh orward. For example, if the user has
previously moved forward by 10 units, the opposite ac on is to move backwards 10 units.
Structuring State
4
Self-review 4.1 What are the values of the variables a, b, c and d a er the following statements have been
executed?
a=1b=2c=a+bd=a+c
Self-review 4.2 How many elements are in the dic onary someData a er the following code has been
executed?
someData = { }
someData[’cheese’] = ’dairy’ someData[’Cheese’] = ’dairy’
without wri ng a Python program or using the Python interpreter, answer the following:
Self-review 4.6 Referring to the coffee/cola vending machine state transi on diagram (page ??), what
happens if the consumer puts three tokens into the machine without pressing any
bu ons?
Self-review 4.7 Which of the following are types mutable and which are immutable:
int, list, float, tuple, str.
All the types listed are mutable except for tuple and str.
Self-review 4.8 What happens when the following statement is executed as the first statement of a
program?
x , y , z = 1 , 2 , x ** 3
There is an error – the excep on NameError is raised. All the expressions on the right-hand side are
evaluated before any assignments are done so x is being used before it is assigned.
Self-review 4.9 For each of the following lines, using subs tu on, hand-evaluate the following sequence:
x,y,z=1,2,3z,y,x=x,z,yx,y,z=(z+1),(
x - 2 ) , ( y * 3 ) y , z , x = ( y / x ) , ( x * y ) , ( z ** x )
Self-review 4.11 Draw a state transi on diagram for a two-bit binary counter. A binary counter is a digital
circuit that has a clock input and an output that gives the number of clock cycles that
have been counted. A two-bit binary counter only has two output connec ons, which
can have the value of either 1 or 0. This means that a two-bit counter can count from
0 to 22−1 and back to 0 again.
Programming Exercises
Self-review 4.12 Draw a state transi on diagram for a PIN (Personal Iden fica on
Number) recognizer. If the user enters ‘1’ followed by ‘8’ followed by
‘5’ followed by ‘0’ followed by ‘enter’, the machine should enter a state
called ‘accept’. If the user enters any other combina on of numbers,
followed by ‘enter’ the machine should enter a state called ‘reject’. Is
this program a lexer?
29
Self-review 4.13 The implementa on of cipherCharacter on page ?? has a bug in it even
though this bug may never appear in normal use. What is the bug and
how can it be fixed?
The problem is that there is no wrap around, and the chr func on requires its parameter to be in
range(256).
Self-review 4.14 What are the types of variables a and b in the following code:
a=(1)
b=(1,)
Self-review 4.15 What is the types and value of y a er execu ng the following code:
x=[1,2,3,4,5]
y=x[:]
Both x and y are lists. They have the same value, which is [1, 2, 3, 4, 5].
Programming Exercises
1. Try running this small program. What are the values of a and b a er
the swap?
2. Why is the result not a having the value 20 and b having the value 10
as appears to be the inten on from the use of the word swap in the
code?
3. Modify the code so that the final result is a having the value 20 and b
having the value 1 using simultaneous assignment to swap the values.
4. Many languages, such as C, C++, Java, do not have simultaneous
assignment. Modify the program so that it successfully swaps the two
values without using simultaneous assignment.
1. Both a and b have the value 20.
2. Because the line a = b sets a to 20, leaving b as it was.
3. a, b = b, a 4. a = 10 b = 20
print "Before swapping a=%d, b=%d" % (a, b)
Structuring State
# Swap values temp = a a = b b =
temp
print "A er swapping a=%d, b=%d" % (a, b)
Exercise 4.2 This ques on is based on a func on for stepping through a representa on of a pack of cards.
The exact nature of the cards isn’t important. We use a list to represent pack and in our
example we use numbers between 1 and 5 as cards. They could equally be numbers and suits
as tuples, strings of character names, etc. Here’s the func on:
# A hand of cards cards = [ 1 , 5 , 3 , 4 , 2 , 3 , 2 ]
Exercise 4.3 Write a program to create a frequency table using a dic onary from a set of input values. The
program should repeatedly asks the user for an input. The input could be anything at all. As
each input is gathered, see if it exists as a key in the dic onary. If it does not exist, associate
the input as a key with the number 1. If it does exist, add one to the value already associated
with it and add it back to the dic onary. If the value associated with this key is now greater
than or equal to 3, print a message that looks something like “Dear user, you have entered
the word ‘discombobulated’ 3 mes!”
Programming Exercises
Frequency tables such as this are o en used for storing histogram data. We
will look at actually drawing histograms later (Chapter 8). Frequency tables
are also used in some sor ng algorithms.
Hint: You will need an infinite loop and to use the raw_input func on.
Exercise 4.4 Write the Python program that manages the state of the two-bit binary counter from
Self-review 4.11
Exercise 4.5 The lexer in Sec on ?? can only recognize non-nega ve integers. Improve the
program by adding code to deal with nega ve numbers.
Exercise 4.6 Create a program for storing a week’s worth of rainfall data. Use a list to store
each day’s value, entered sequen ally by the user. When an en re week has
been input, display the days with the minimum and maximum rainfall.
import math
Exercise 4.7 Extend your answer to the previous exercise so that it also displays the mean and standard
devia on of the values. The mean is the sum of all the values divided by the number of
Structuring State
values. The standard devia on is the square root of the sum of the squares of the difference
between each value and the mean, divided by the number of items.
import math
def rainfall ( ) : days = [ ’Mon’ , ’Tue’ , ’Wed’ , ’Thu’ , ’Fri’ , ’Sat’ , ’Sun’ ] rain = [ ] for
i in range ( 7 ) : r = input ( ’Please enter the rainfall for ’ + days[i] + ’: ’ )
rain.append ( r )
# Minimum and Maximum minimum =
rain[0] maximum = rain[0] for i in rain :
if i < minimum : minimum = i if i > maximum :
maximum = i
mean = sum ( rain ) / len ( rain )
sd = math.sqrt ( sum ( [ ( x - mean ) ** 2 for x in rain ] ) / ( len ( rain ) - 1 ) )
# Print everything to the console print ’Min rainfall for this week:’ ,
minimum print ’Max rainfall for this week:’ , maximum print ’Mean
rainfall for this week:’ , mean print ’Standard devia on rainfall for
this week:’ , sd for i in range ( len ( rain ) ) : print ’Rainfall for’ , days[i]
, ’=’ , rain[i]
Exercise 4.8 Calcula ng sta s cs such as maximum, minimum, mean and standard devia on is a common
task. Now that you have a program to do it, package the code up into a func on that can be
used again in future.
Exercise 4.9 A “wobbly” number is one in which the digits alternate between being higher and lower than
the preceding one. Here are some wobbly numbers: 19284756242, 90909, 0909. Using what
you have learned
Challenges
Exercise 4.10 The following code was wri en before the programmer had drunk their
morning coffee, i.e. they were not properly awake at the me. It is
supposed to add 3% to all the values in the variable salary_scale. However,
33
there is one very important bug in this code. Find and fix the bug to make
sure everyone gets their 3% pay rise!
salaryScale = ( 20000 , 21500 , 23000 , 24500 , 26000 , 27500 , 29000 )
for i in range ( len ( salaryScale ) ) :
salaryScale[i] += salaryScale[i] * 0.03 print
salaryScale
write a func on to sort the list – i.e. your func on should return the list:
[ 1 , 2 , 6 , 22 , 43 , 54 , 78 , 99 ]
You can use any method you like to sort the list. Good answers to this problem
will work on any list, not just the one we’ve given here.
Challenges
Challenge 4.1 Imagine a fic onal land where monetary units aren’t based on decimal orders.
In this land, we have 3 basic units of currency:
2. Write a func on called enBlinkHoojaBung that takes a number of Blinks and outputs
its equivalent in Blink, Hooja and Bung, using the smallest number of coins. Coins in
our imaginary land are made of a very heavy metal, so this is important. If the func on
is called with the value 506, the output should be:
506 Blinks is worth 2 Bung, 1 Hoojim and 6 Blinks.
You will need the remainder operator (%).
3. Rewrite enBlinkHoojaBung so that it returns a tuple of Blinks, Hooja and Bung values
instead of wri ng to the screen. The last example would return ( 2 , 1 , 6 ).
Structuring State
Challenge 4.2 Referring back to Exercise 4.2, write a program that uses two hands of cards (two lists) to
play a simple game of “snap”. No cards change hands, but when two iden cal cards are
played, a message should be printed.
Hint: If your input is the following string: ‘12345.9876’ what do you have to do to each
character in the string to generate your float? How are the numbers before the
decimal point different to the numbers a er the decimal point? Make sure you have
an algorithm that works correctly on paper before you start coding and draw a state
transi on diagram for the scanning part of your lexer.
Func onally Modular
5
Self-review 5.1 Which names are local, which are global and which are built-in in the following code fragment?
space_invaders = [ . . . ] player_pos = ( 200 , 25 ) level
= 1 max_level = 10
def play ( ) :
...
while ( level < max_level +1 ) : if len ( space_invaders ) == 0 :
level += 1 con nue . . .
Global names:
• space_invaders
• player_pos
• level
• max_level Built-in names:
• len
...and there are no local names.
but this next func on is not referen ally transparent, because it updates the variable a:
a = 10 def example ( ) : global a
a=a+1
return a * 10
Func onally Modular
Self-review 5.5 What list of lists does the following list comprehension evaluate to?
[ [ ’#’ for col in range ( 3 ) ] for row in range ( 3 ) ]
Self-review 5.7 In Python modules, what is the following code idiom used for?
if __name__ == ’__main__’:
...
Self-review 5.9 What are the following special variables used for?
1. __author__
Self-Review Ques ons
2. __date__
3. __copyright__
4. __version__
5. __revision__
6. __license__
7. __credits__
Self-review 5.10 What is the result of execu ng the following Python code?
l = [ i for i in range ( 1 , 100 ) ] map ( lambda
x : x ** 3 , l )
The func on geni returns a generator which generates the integers from 1 to n. For example:
>>> def geni ( n ) :
... for i in range ( n ) :
... yield i
...
>>> g = geni ( 10 )
>>> g.next ( ) 0
>>> g.next ( ) 1
>>> g.next ( ) 2
>>> g.next ( )
3
>>> g.next ( ) 4
>>> g.next ( )
5
>>>
Self-review 5.15 Using the documenta on on the Python website, find out what the excep on StopItera on is used
for.
Programming Exercises
Func onally Modular
Exercise 5.1 The following Python code represents a Tic-Tac-Toe board as a list of
lists:
[ [ ’#’ , ’o’ , ’x’ ] , [ ’#’ , ’#’ , ’o’ ] , [ ’x’ , ’#’ , ’o’ ] ]
Exercise 5.2 Convert the following itera ve func ons into recursive func ons:
1. def sum_even ( n ) :
total = 0 for i in range ( 2 , n
unc on +1,2):
d as a total += i return
on, and total
func on
d as an
on. 2. def min ( l ) : m = 0 for i in l :
if i<m : m = i return m
Programming Exercises
3. def prod ( l ) :
product , i = 1 , 0 while i <
len ( l ) : product *= l[i] i += 1
return product
Hint: You may find it useful to add an extra parameter to the recursive version of min.
Exercise 5.3 Convert the following recursive func ons into itera ve ones:
1. def sum_odd ( n , total ) : if n == 1 : return total elif n % 2 == 0 : return sum_odd ( n - 1 , total ) else
: return sum_odd ( n - 2 , total + n )
39
2. def max ( l , n ) :
if l == [ ] : return n elif l[0] > n : return max (
l[1:] , l[0] ) else : return max ( l[1:] , n )
3. def mylen ( l , n ) :
if l == [] : return n else : return mylen (
l[1:] , n +1 )
def sum_odd ( n ) :
total = 0 for i in range ( n + 1 ) : if
i % 2 != 0 :
total += i return total
def max ( l ) : m = 0
if l == [ ] : return None # Dummy value else : m =
l[0] for i in l :
if i > m : m = i
return m
Exercise 5.4 The following code is a module that provides func ons for drawing some simple
shapes using the Python Turtle module. Copy the code into a file called shape.py and
add in:
Make sure you use pydoc to generate a webpage containing your documenta on.
__author__ = ’Sarah Mount’ from turtle import *
def square ( n ) :
for i in range ( 4 ) : forward ( n ) le ( 90 )
Exercise 5.5 Use map and lambda to turn a list of integers from 1 to 100 into a list of even numbers from 2 to 200.
Exercise 5.7 Use a list comprehension to generate a list of odd numbers from 0 to
100.
Exercise 5.8 Write a generator func on (using the yield keyword) that generates factorial numbers.
Write a recursive Python func on to implement Ackermann’s Func on. How many recursive calls will
be required to evaluate A(2,3)?
Programming Exercises
We can find the number of recursive calls needed to compute ackermann ( 2 , 3 ) using a
walk-through. This is similar to the work we did in Sec on ?? 3.3.1 when we looked at
the recursive defini on of the factorial func on.
Each number is generated by adding the two above it. Write a recursive func on to generate the first
n lines of Pascal’s Triangle.
Challenges
Using a numbering such as this one makes the answer to this challenge simpler!
Func onally Modular
4. next_play ( ) – This func on should ask the user for the next move they want to play. You
should make sure that the user knows whether x or o is currently playing. You can assume
that the user will enter an integer value. You should s ll check that the integer the player
has provided is between 0 and 8 inclusive.
Challenges
5. play ( ) – This is the top-level func on that tells Python how to play Tic-Tac-Toe. The
algorithm for game play is:
• If one of the players has won the game, print a message on the
screen to congratulate them.
• If no-one has won the game, then:
– Use the next_play func on to get the current player’s next move.
– Play the next move by calling the place_counter func on.
– Print the new board.
– Change the current player – either from ’x’ to ’o’ or from ’o’ to ’x’.
You will also need two global variables, one to store the current state of the
board and one to say which player is playing next.
Below is an outline of the module to get you started – make sure you add some
documenta on and make good use of Python’s special variables, like __author__
and __version__.
board = [ [ ’#’ for col in range ( 3 ) ] for row in range ( 3 ) ]
o_playing = True def play ( ) :
# Your code here! def
next_play ( ) :
# Your code here! def
has_won ( ) :
# Your code here! def
place_counter ( ) :
# Your code here! def
print_board ( ) :
# Your code here!
if __name__ == ’__main__’:
play ( )
Challenge 5.2 One reason for selec ng a recursive version of an algorithm over an itera ve one, or
vice versa, is running me. There are various ways of assessing whether one
algorithm is faster than another. Big O nota on is a very important one – we will
come to this in Chapter 10. A technique for assessing the speed of programs
implemen ng algorithms is to execu ng benchmarks. Benchmarks require us to be
able to me the execu on of a program. Python helps us here, as it provides a
module called meit that can be used to me the execu on of Python expressions.
Here is an example of the meit module in use:
>>> import meit
>>>
>>> def is_prime ( n ) :
43
... return not bool ( filter ( lambda x: n%x == 0, range ( 2 , n ) ) )
...
>>> def primes ( n ) :
... return filter ( is_prime , range ( 2 , n ) )
...
>>> t = meit.Timer ( ’primes ( 100 )’ , ’from __main__ import primes’ )
>>> print t. meit ( 500 )
1.47258400917
>>>
Here, we have wri en some code to me one of our prime number generators, and found out
how long it has taken Python to execute the code 500 mes. We did this by crea ng an object
called meit.Timer that took a call to our primes func on as its first argument. The second
argument, ’from __main__ import primes’ tells the meit module where it can find the primes
func on – in this case in the __main__ namespace.
The argument to the meit method, 500, means ’execute the code 500 mes’. Python code
generally executes very quickly, so ming a very short piece of code that only runs once can be
inaccurate. So, instead, we can ask meit to me the code over several hundred or thousand runs,
which will give us more accurate informa on. In the example above, the code took
1.47258400917 s to run.
For this challenge, test the me of execu on of all the prime number generators we have
presented in this book, ming them using the meit module, to determine which is the fastest.
Challenge 5.3 Chess is played on an 8×8 board. A queen may a ack any piece on the same row, column or diagonal
as herself.
The Eight Queens Problem involves placing eight queens on a chess board in such a way that no
queen is a acking any other – so, there must be at most one queen on any row, column or
diagonal.
There are 92 solu ons to the Eight Queens Problem and the challenge is to write a program that
finds all of them.
Hint: Think about how to represent the board. A list of lists of Booleans might be a sensible choice,
but are there other op ons? Whatever you use, you will probably want to make sure that you
can print chess boards in a human-readable format, such as this:
Q X X X X X X X
X X Q X X X X X
X X X X X Q X X
X Q X X X X X X
X X X X X X X Q
X X X Q X X X X
X X X X X X Q X
X X X X Q X X X
The Eight Queens Problem is the subject of the classic paper, Program Development by Stepwise
Refinement by Nicklaus Wirth. You
can find his paper at the ACM ’classics’ website: h p://www.acm.org/ classics/dec95/
Classy Objects
6
r is an object, random is a method which is a member of the object r and () is the (empty) list of arguments passed
to the method random.
Self-review 6.6 Why is the method name __init__ special, and for what reason(s)?
Self-review 6.8 Why is there an apparent difference between the number of parameters in the defini on of a
method and the number of arguments passed to it when called?
Self-review 6.10 Is the method bar in the following code legal in Python?
class Foo :
def __init__ ( self ) : self.foo = 1
def bar ( flibble ) :
45
print flibble.foo
1. __add__
2. __eq__
3. __lt__
4. __or__
5. __ne__
6. __div__
7. __ge__
Self-review 6.14 Why is it usually thought to be a bad thing to use global statements?
Self-review 6.15 What does the __ mean in the name __foobar in the following
class?
Programming Exercises
class Foo :
def __init__ ( self ) :
self.__foobar ( )
Classy Objects
def __foobar ( self ) :
print ’foobar’
The double underscore means that the method __foobar can only be called by code within the class Foo.
For example:
>>> class Foo:
... def __foobar(self):
... print ’foobar’
... def foobar(self): ...
self.__foobar()
...
>>> f = Foo()
>>> f.foobar() foobar
>>> f.__foobar()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
A ributeError: Foo instance has no a ribute ’__foobar’
>>>
Programming Exercises
Exercise 6.1 Create a class to represent a single die that can have any posi ve integer number of
sides. This kind of die might be used when playing role-playing games ( RPGs).
class AnyDie:
def __init__ ( self , sides ) : assert type ( sides ) ==
type ( 0 ) assert sides > 0 self.sides = sides
self.generator = random.Random ( )
self.current = 1
self.representa ons = map ( lambda x : ’*’ * x , range ( self.sides + 1 ) )
def __str__ ( self ) : return
self.representa ons[self.current]
def roll ( self ) :
self.current = self.generator.randint ( 1 , self.sides ) return
self.current
Exercise 6.2 Write a class to represent an RPG character’s money pouch. Money should be stored
as an integer, with methods for adding money and removing money. The removing
method should take a value as parameter. If there is enough money, the value is
removed from the money in the pouch and True is returned. If there is not enough
money, False is returned.
Exercise 6.3 Write a simple RPG character class. The character should have a name, a money pouch and an inventory.
The name should be stored as a string, the money pouch should be an instance of the pouch from the
47
previous exercise and the inventory should be a dic onary in which keys are item names and values
are the number of items held by the player.
Ensure that there are methods for adding items to, and removing items from, the inventory.
There should be a __str__ method that returns something that can be printed. For example:
print playerA
Might display:
-------------------------
Duncan Disorderly
-------------------------
Money: 235 gold pieces
-------------------------
Knapsack contains:
Arrow: 12
Rubber Sword: 1
Felt pped pen: 2
Imita on fur coat: 23
-------------------------
class Pouch :
def __init__ ( self , money ) : self.money = money
def add ( self , money ) : self.money += money
def remove ( self , money ) : if not ( self.money > money ) : return False
self.money -= money return True
def __str__ ( self ) : return ’Money: ’ + str ( self.money ) + ’ gold pieces.’
class Character :
def __init__ ( self , name ) : self.name = name self.pouch =
Pouch ( 0 ) self.inventory = { }
def pickupItem ( self , item ) :
if self.inventory.has_key ( item ) : self.inventory[item] += 1
else:
self.inventory[item] = 1
def dropItem ( self , item ) :
if not self.inventory.has_key ( item ) : pass elif self.inventory[item] < 1:
pass else : self.inventory[item] -= 1 def pickupMoney ( self , money ) :
Programming Exercises
self.pouch.add ( money )
def dropMoney ( self , money ) :
self.pouch.remove ( money )
def __str__ ( self ) :
sep = ’----------------\n’
s = sep + self.name + ’\n’ + sep + str ( self.pouch ) + ’\n’ + sep + ’Knapsack contains:\n\n’ for key
in self.inventory.keys ( ) :
if self.inventory[key] > 0 :
s += ( ’\t’ + key + ’: ’ + str ( self.inventory[key] ) + ’\n’ )
s += sep return s
Classy Objects
Exercise 6.4 Implement the mul plica on opera on for the Matrix class. The trick to
implemen ng mul plica on is to realize you need three, nested loops:
if len ( self.data[0] ) != len ( m.data ) :
raise ValueError , ’Matrices not of the suitable shapes for mul plica on.’
n = zeros ( len ( self.data ) , len ( m.data[0] ) ) for row
in range ( len ( n.data ) ) :
for column in range ( len ( n.data[0] ) ) :
for i in range ( len ( self.data[0] ) ) :
n.data[row][column] += self.data[row][i] * m.data[i][column]
return n
Exercise 6.5 Implement __ge tem__ for the Matrix class so that we can rewrite the drawTriangle func on to
work with a triplet of 2×1 matrices:
def drawTriangle ( coordinateMatrix ) :
turtle.up ( ) turtle.goto ( coordinateMatrix[0][0][0] ,
coordinateMatrix[0][1][0] ) turtle.down ( ) turtle.goto (
coordinateMatrix[1][0][0] , coordinateMatrix[1][1][0] ) turtle.goto (
coordinateMatrix[2][0][0] , coordinateMatrix[2][1][0] ) turtle.goto (
coordinateMatrix[0][0][0] , coordinateMatrix[0][1][0] )
We can use __ge tem__ in exactly the same way that we would use any list subscript. For example:
>>> m = Matrix(2,2)
>>> m[(0,0)]
0.0
>>>
Exercise 6.6 Write a class Account that stores the current balance, interest rate and account
number of a bank account. Your class should provide methods to withdraw,
deposit and add interest to the account. The user should only be allowed to
withdraw money up to some overdra limit. If an account goes overdrawn, there
is fee charged.
Exercise 6.7 Write a small class to represent the light switch state machine from Sec on ??.
Provide a single method to change the state of the switch and method called isOn
which returns True if the switch is on and False if it is off. Make sure you override
the __str__ method so that light switches can be printed to the console.
class Account:
interest_rate = 0.05 overdra _limit =
500 overdra _charge = 50 def __init__
( self , number ) : self.number =
number self.balance = 0
def deposit ( self , amount ) :
if amount < 0 : raise ValueError, "Can’t deposit a nega ve amount of money." self.balance +=
amount
def withdraw ( self , amount ) :
if amount < 0 : raise ValueError, "Can’t withdraw a nega ve amount of money." if amount > (
self.balance + Account.overdra _limit ) : raise ValueError, ’Out of credit.’ if amount >
self.balance :
49
self.balance -= amount
self.balance -= Account.overdra _charge
else :
self.balance -= amount
def __str__ ( self ) :
sep = ’------------------’
s = ’\nAccount\n’ + sep + ’\n’ s += ’Account number: ’ + str(self.number) + ’\n’ + sep
+ ’\n’ s += ’Overdra limit: ’ + str(Account.overdra _limit) + ’\n’ s += ’Overdra
charge: ’ + str(Account.overdra _charge) + ’\n’ + sep + ’\n’ s += ’Account balance: ’
+ str(self.balance) + ’\n’ + sep + ’\n’ return s
Exercise 6.8 Write a program which uses the Stack class. Your program should begin by prin ng a menu
to the user:
1. Add new data to stack
2. Print stack
3. Remove datum from stack
4. Exit
You should allow the user to enter 1, 2, 3 or 4 to select their desired ac on and you
should write code to implement the four possible op ons.
Exercise 6.9 Amend your program from Exercise 6.8 to use a Queue as the data structure used to store data
in.
if __name__ == ’__main__’ :
q = Queue ( ) while True : print
menu m = 0 while m < 1 or m > 4 :
m = input ( ’Enter: ’ )
Challenges
if m == 1 :
datum = raw_input ( ’Enter datum: ’ ) q.add ( datum
)
elif m == 2 :
print ’Queue:’ , q , ’\n’ elif m == 3 :
datum = q.remove ( )
print ’Removed’ , datum , ’from the queue.\n’
elif m == 4 :
print ’Goodbye!’ break
Exercise 6.10 A priority queue is an abstract data type similar to the queue introduced in Sec on
?? and Sec on ??. A priority queue associates a priority with each stored item and
always stores the items so that the elements with the highest priority are at the
Classy Objects
‘top’ of the queue and are the first to be removed – i.e. the items in a priority queue
are sorted by priority. Create a PriorityQueue class based on the Queue class:
1. The add method should take two parameters, an item to store and a priority,
which should be an integer.
2. The add method should ensure that when new data is added to the priority queue,
it is added as a tuple which contains both the data and its priority. Make sure that
data is always stored in priority order.
3. The remove method should return queue items, not tuples – i.e.
the priority associated with the returned item can be ignored.
Challenges
Challenge 6.1 Currently, the n-faced die (see Exercise 6.1) is unable to display its spots and must instead
rely on displaying a number.
Your task is to write a func on that returns a string representa on of the die face for
a given number. For example, this:
print makeFace ( 9 ) might display:
***
***
***
The algorithm is up to you, but do remember about integer division and the remainder
operator (%)
Now that you can make faces with an arbitrary number of spots, add this func onality
to your n-sided die class.
Challenge 6.2 Extend your RPG character class to hold values for health points (HP), a ack points (AP)
and defence points (DP).
Add an a ack method that takes a character instance as a parameter. This is your opponent.
If the character’s AP is greater than the opponent’s DP, the difference is subtracted from the opponent’s HP. So, if
I a ack with a power of 7 and my opponent has a defence power of 6, they lose 1 health point. If they have a
defence power of 9, they sustain no damage.
Write a program that demonstrates your character class by crea ng two characters that take it in turns to bop each
other un l one of them runs out of HP.
class Character :
def __init__ ( self , name ) : self.name = name self.pouch = Pouch ( 0 ) self.inventory
= { } self.hp = 100 self.ap = random.randint ( 1 , 100 ) self.dp = random.randint (
1 , 100 )
def a ack ( self , enemy ) : if self.ap > enemy.dp : enemy.hp -= ( self.ap - enemy.dp )
def pickupItem ( self , item ) :
51
if self.inventory.has_key ( item ) : self.inventory[item] += 1
else:
self.inventory[item] = 1
def dropItem ( self , item ) :
if not self.inventory.has_key ( item ) : return elif self.inventory[item] < 1 : return else :
self.inventory[item] -= 1
def pickupMoney ( self , money ) : self.pouch.add ( money )
def dropMoney ( self , money ) : self.pouch.remove ( money )
def __str__ ( self ) :
sep = ’----------------\n’
s = sep + self.name + ’\n’ + sep
s += ’Health:\t’ + str(self.hp) + ’\n’ s += ’A ack:\t’ + str(self.ap) + ’\n’ s +=
’Defence:\t’ + str(self.dp) + ’\n’
s += sep + str ( self.pouch ) + ’\n’ + sep + ’Knapsack contains:\n\n’ for key in self.inventory.keys ( ) : if
self.inventory[key] > 0 :
s += ( ’\t’ + key + ’: ’ + str ( self.inventory[key] ) + ’\n’ )
s += sep return s
if __name__ == ’__main__’ :
player1 = Character ( ’Player 1’ )
Challenges
Self-review 7.1 What do the terms ’subclass’ and ’superclass’ mean in object-oriented programming?
Self-review 7.4 What is the difference between single and mul ple inheritance?
1. Associa on.
2. Aggrega on.
1. Widgets.
2. Callbacks.
3. Events.
4. Event loops.
5. Event handler.
Self-review 7.10 What is polymorphism? How is it related to object-oriented programming? Give a short
example of a piece of code that exploits polymorphism.
Inheri ng Class
Self-review 7.11 Using the expression evaluator from Sec on ?? (page ??), draw the object diagram that
represents the following Python expression:
Mul ( 3 , Div ( Add ( 1 , 2 ) , Sub ( 5 , 8 ) ) )
Self-review 7.13 What does the name self mean? Is self a Python keyword?
Programming Exercises
Exercise 7.1 Extend the traffic light program to include a short red+amber ’prepare to go’ state as is used for
traffic lights in the UK, and other places.
Exercise 7.2 Create a subclasses of your Account class (from Exercise 6.6) called CreditAccount in which the
user is charged a set amount for every withdrawal that is made. If the user is overdrawn, the
withdrawal charge is doubled.
Exercise 7.3 Create a subclasses of your Account class (from Exercise 6.6) called StudentAccount in which
new accounts start off with a balance of £500 and an overdra of up to £3000 is allowed, with
no charges for withdrawal.
1. DrawableRectangle
2. DrawableSquare
3. DrawableCircle that work using the Tkinter package.
Exercise 7.5 Create a class called Number and two subclasses Binary and Roman for dealing with different
sorts of number representa on. The constructors to Binary and Roman should take a string
argument so that you can use them like this:
b = Binary ( ’11010101’ ) r = Roman (
’MCMLXXVIII’ )
Programming Exercises
In your Number class you need to have methods that are common to all types
of number representa on:
55
1. You’ll want a private method called __to_int that returns an ordinary
integer representa on of the calling object.
2. You’ll need to override the built-in method __str__ that returns a string
representa on of the number which the calling object represents.
3. You’ll need to override the __int__ method that is used by calls to the int
func on which converts its argument to an integer.
In all three classes you’ll need an __int__ method that calls the __to_int
method in the calling object – even though Binary and Roman are subclasses
of Number, they s ll need an __int__ method of their own. Why is this? If
you’re not sure you have understood why this works, when you’ve finished
this exercise, comment out the defini on of __int__ in Binary and Roman and
see what happens.
You’ll need to override __to_int in the Binary and Roman classes. For the
method in Roman, you may want to use the algorithm in Sec on ?? to parse
a Roman numeral into an integer. Make the LUT (lookup table) a class variable
(rather than an instance variable).
For the Binary class, you’ll need to convert between binary and decimal. As a
reminder of the algorithm, here’s an example:
1010101 → 1×26+0×25+1×24+0×23+1×22++0×21+1×20
When you have wri en all your classes you’ll need to test them. Below is the
beginnings of a test program you can use to help you:
def test ( ) :
data = [
( Binary ( ’0’ ) , 0 ) , ( Binary ( ’1’ ) , 1 ) ,
( Binary ( ’10’ ) , 2 ) , ( Binary ( ’11’ ) , 3 ) ,
( Binary ( ’100’ ) , 4 ) , ( Binary ( ’101’ ) , 5 ) ,
( Binary ( ’10101010101’ ) , 1365 ) ,
( Roman ( ’I’ ) , 1 ) , ( Roman ( ’II’ ) , 2 ) ,
( Roman ( ’IV’ ) , 4 ) , ( Roman ( ’VI’ ) , 6 ) ,
( Roman ( ’IX’ ) , 9 ) , ( Roman ( ’X’ ) , 10 ) ,
( Roman ( ’XI’ ) , 11 ) , ( Roman ( ’MM’ ) , 2000 ) ,
( Roman ( ’MCMLXXVIII’) , 1978 )
]
for entry in data :
assert int ( entry[0] ) == entry[1]
When your code works you should get no asser on failures when you execute the test
program.
Exercise 7.6 On page ?? we introduced the Diamond Problem of object-oriented programming languages
and explained how Python deals with it. In
Inheri ng Class
this exercise you will explore how Python handles mul ple inheritance.
Below are class defini ons that exhibit the Diamond Problem. Start off by drawing a
diagram to show the inheritance rela onships between the five classes.
Create objects that are instances of classes D and E. Call the foobar and barfoo
methods in both objects. What is the difference between the output from the two
objects? Why does this happen?
class A :
def foobar ( self ) : print ’Class A’
def barfoo ( self ) :
print ’barfoo from class A!’
class B ( A ) :
def foobar ( self ) : print ’Class B inherits
from A’
def barfoo ( self ) :
print ’barfoo from class B!’
class C ( A ) :
def foobar ( self ) : print ’Class C inherits
from A’
def barfoo ( self ) : print ’barfoo from
class C!’
class D ( B , C ) :
def __init__ ( self ) :
return
class E ( C , B ) :
def __init__ ( self ) :
return
Exercise 7.7 Write a program that takes a list of Point objects (from Sec on ??, page ??) and draws
them with the Turtle module. Your code should be polymorphic. A Point2D object
represents a point on the screen, but if you need to move the turtle to a point
represented by a Point3D object, just ignore the z component.
Here is some test data to get you started:
square = [
Point2D ( 0.0 , 0.0 ) , Point2D ( 100.0 , 0.0 ) , Point2D ( 100.0 , 100.0 ) ,
Point2D ( 0.0 , 100.0 ) , Point2D ( 0.0 , 0.0 )
]
rectangle = [
Point2D ( 0.0 , 0.0 ) , Point2D ( 200.0 , 0.0 ) , Point2D ( 200.0 , 100.0 ) ,
Point2D ( 0.0 , 100.0 ) , Point2D ( 0.0 , 0.0 )
]
pentagon = [
Point2D ( 0.0 , 0.0 ) , Point2D ( 100.0 , 0.0 ) , Point2D ( 131.0 , 95.0 ) ,
Point2D ( 50.0 , 154.0 ) , Point2D ( -30.0 , 95.0 ) , Point2D ( 0.0 , 0.0 )
]
square3 = [
Point3D ( 0.0 , 0.0 , 1.0 ) , Point3D ( 100.0 , 0.0 , 1.0 ) , Point3D ( 100.0 , 100.0 , 1.0 ) ,
Point3D ( 0.0 , 100.0 , 1.0 ) , Point3D ( 0.0 , 0.0 , 1.0 )
Programming Exercises
57
]
square23 = [
Point3D ( 0.0 , 0.0 , 1.0 ) , Point2D ( 100.0 , 0.0 ) , Point2D ( 100.0 , 100.0 ) , Point3D
( 0.0 , 100.0 , 1.0 ) , Point2D ( 0.0 , 0.0 )
]
Hint: To draw these shapes elegantly, it would be sensible to li the ’pen’ of the
turtle off the screen before moving from the origin to the first point.
Exercise 7.8 Write a version of the Caesar cipher from Sec on ?? (page ??) with a simple
GUI. Allow users to enter text in a text box, then generate an enciphered
version of the text when they press a bu on. Let users change the key that is
used by the cipher either by providing a text box to enter the key, or a drop-
down list of available keys.
You should research the HCI literature to see which of these two op ons the
HCI community believe is a be er choice of data entry in this context.
Exercise 7.9 Extend the Caesar cipher GUI by adding a bu on that causes deciphering (rather than
enciphering) of the text in the text box.
Exercise 7.10 Write a simple color picker using Tkinter. You should provide the user with
three sliders (using the Tkinter.Scale class) which they can use to set red,
green and blue values. Whenever a slider is moved, a callback should be
issued that changes the background color in a Canvas widget.
Exercise 7.11 Extend your answer to the previous exercise to allow users to also select
specific colors from a drop-down list. Here is a random list of
colors that you may want to include:
Challenges
Inheri ng Class
Challenge 7.1 Write a GUI for the expression evaluator in Sec on ??. Let the user enter an expression and
press a bu on to have that expression evaluated. To make this a bit simpler, you might want
to start out with a GUI where the user enters a Python expression such as this:
Add(1, 2)
You’ll need to turn the string from the user into a real Python object. Fortunately, Python
provides a func on called eval that does that. Here’s an example of eval in ac on:
Note that you can only use eval with expressions, not with statements!
Challenge 7.2 This challenge is to create a GUI that allows you to apply various image processing algorithms
to images. To do this you will need an image processing library. Python doesn’t come with
one as standard, but you can download the Python Imaging Library ( PIL) from
h p://www.pythonware.com/ – it is free. You will also need the PIL handbook
h p://www.pythonware.com/library/pil/handbook/, which is the best documenta on available
for the library.
The GUI should allow you to select an image, maybe using a list-box or a modal dialog from
the tkFileDialog module. You will also need some bu ons that apply transforma ons to the
current image and display the processed image. To get you started, we have provided some
code below that uses Tkinter to display an image, and some examples of image processing
using PIL.
The nega ve of an image has the amount of red, green and blue in each image inverted. The
nega ve of a red pixel (255, 0, 0) is a cyan pixel (0, 255, 255). The nega ve of a black pixel
(0, 0, 0) is a white pixel (255, 255, 255). So to create the nega ve of an image, we just have
to subtract the current red, green and blue values of each pixel from 255. Here’s an example
image and the code that implements the transforma on:
Challenges
59
’’’Produces the nega ve of a posi ve color image.’’’
if __name__ == ’__main__’ :
tle = ’Color->Nega ve Using Python Image Library’ filename =
sys.argv[1] image = Image.open ( filename , ’r’ ) image.load ( ) nega ve
= image.point ( lambda pixel : 255 - pixel ) viewport.display_image (
nega ve , tle )
Two things to note here. Firstly, the PIL library stores the red, green and blue pixel values of
an image as separate list elements (rather than storing a list of three-tuples). Secondly, each
PIL image has a method called point that allows us to apply a transforma on on each pixel
value in the image. point can be used in two ways: you can either pass it a func on or
lambda expression to apply to each pixel value, or you can pass it a lookup table. Above we
have used a lambda expression.
The PIL library also defines a number of filters that can be used to perform transforma ons
on images. These are located in the ImageFilter module. To use a filter, you create an
instance of a filter class and pass it to the filter method of an image object.
This example creates an embossed version of the image in which the edges of the objects
in the image appear raised above the surface of the image:
’’’Emboss an image.’’’
Below is the code for the viewport module that we have used in the examples above:
’’’View a PIL image on a Tkinter canvas.’’’
def display_image ( pil_image, tle ) : ’’’Take a PIL image and display it in a GUI.’’’ root = Tkinter.Tk ( ) root. tle (
tle ) im_width, im_height = pil_image.getbbox ( )[2:4] canvas = Tkinter.Canvas ( root, width=im_width,
height=im_height ) canvas.pack ( side=Tkinter.LEFT, fill=Tkinter.BOTH, expand=1 ) photo =
ImageTk.PhotoImage ( pil_image )
item = canvas.create_image ( 0, 0, anchor=Tkinter.NW, image=photo ) Tkinter.mainloop ( )
Self-review 8.1 We can store the contents of dic onaries, lists and tuples in a file and, using eval, retrieve them while
keeping their type and structure. Does this mean that the opera ng system specifically supports these
types?
Self-review 8.2 Why should we not use the write mode (’w’) when we wish to add data to an exis ng file?
Self-review 8.3 What mode should be used when adding data to an exis ng file?
Self-review 8.4 If you search your computer’s hard disk, you may find that many files have the same name. Readme.txt,
for example, appears many mes on our hard disks. These files are dis nct and normally have different
contents. How is it that the opera ng system can maintain separate files of the same name?
Self-review 8.5 What is ‘wrong’ with the histogram drawing algorithm on page ???
Hint: The problem is not in the code structure but in the assump on about coordinates.
The problem here is that we had assumed that the bo om le corner was the origin, (0, 0), and that posi ve x was
rightward and posi ve y was upward. In fact the origin is the top le -hand corner with posi ve x rightward and posi ve y
downward. So correc ng the histogram drawing for a more expected appearance, we have to make two rela vely trivial
changes:
canvas.create_rectangle (
( 2 * i + 1 ) * barWidth , height - unitHeight ,
( 2 * i + 2 ) * barWidth , height - ( data[i][1] + 1 ) * unitHeight , fill = ’black’ )
Self-review 8.7 What is the ‘root’ directory in a file system and what is it’s .. file?
Self-review 8.8 In the os module Python has a variable called os.sep which has the value ’/’ on UNIX machines and ’\’ on
Windows computers. What do you think this variable is used for?
Filing Things Away
Self-review 8.9 What are buffers and why does Python use them when opening
files?
Self-review 8.13 What excep on is raised when Python tries to open a file which does not exist?
Self-review 8.14 The check digit in ISBNs tells us whether an ISBN is valid. Can you think of any other
compu ng related ac vi es where check digits (or check sums) are used?
Programming Exercises
Exercise 8.1 Amend the getData method so that the parameter is a file object rather than a file name.
Change the histogram drawing program removing the closing of the file and execute it to
show that the amended getData method works as it should.
Exercise 8.2 Amend the getData method so that the parameter can be either a string giving the name of
the file to be read, or a file object of an already open file.
Exercise 8.3 Evolve the histogram drawing code (your corrected version from Selfreview 8.5 rather than the
faulty version on page ??) so that the bars have labels that show which bin the data is for, and
so that there are indica ons of what the lengths of the bars represent. One approach would
be to draw an axis down the side with ck marks and values. It may also be sensible to write
the actual count of items in the bin above the bar, perhaps resul ng in something like:
Programming Exercises 65
import Tkinter
if __name__ == ’__main__’ :
plot ( [
[ ’1--2’ , 1 ] ,
[ ’2--3’ , 3 ] ,
[ ’3--4’ , 1 ]
])
This is a very simple program for storing a list of words in a file. When executed it
expects the user to enter some words, one per line, finishing with the word “END”.
3. Write a program to read the data file and display a numbered list of the contents, such
as:
1: chicken
2: apple
3: fox
4: aubergine
5: END
4. Note that “END” is always the last word displayed. This isn’t really the behavior we want,
since “END” is meant as a command, not a word. Change the program so that it no
longer stores “END” in the file.
5. There’s s ll a problem: we can’t put the word “END” into the file even if we wanted to.
Maybe we should use the empty string (’’) to signal the user’s desire to quit? Modify the
program to use the empty string to terminate user input.
Exercise 8.5 Using your answer to the previous ques on as a star ng point, write a program that counts
the number of mes each word appears in the data file. Its output might look like this:
Carrot: 3
Cheese: 1
Egg: 6
Tomato: 2
Exercise 8.6 It would be nice if we had a graphical display of word frequency for the previous exercise. Use
the histogram module from earlier in the chapter to display the word frequencies as a
histogram.
Exercise 8.7 Write a program to say how many lines of text there are in a text file the name of which is
obtained by promp ng and reading input from the user.
Exercise 8.8 Write a program to read the contents of a text file and display it in a Tkinter text box.
Exercise 8.9 Write a program to store a list of contact names and telephone numbers, similar to the contact
lists you might find on a mobile phone. The data needs to be stored in a file so that it is
persistent – that is, the data available at the beginning of a new execu on of the program is
the same as at the end of the previous execu on.
Exercise 8.10 Extend the program wri en for the previous exercise so that as new contacts are added, the
program checks for duplicate names and numbers. If the new contact’s name is already in
the database, the message “This person is already entered.” should appear. If the telephone
number is already in the database, the program should display “This person’s telephone
number is already in the database. This could be an error, or a second contact at the same
company. Add anyway?” If the user enters “Y”, the contact is added.
Challenges 67
Challenges
Challenge 8.1 Write a program to display a simple form of digital book. “Books” are text files in which
each block (page) of text is followed by a double dash (--).
When a book is displayed, the first block of text is shown and the program should wait
for the user to press the enter key before displaying the next.
Challenge 8.2 Extend the previous challenge so that it is possible to skip forward by an arbitrary number
of pages. This should be achieved by allowing the user to enter a number before
pressing the enter key. If the number is posi ve, the given number of pages are skipped.
If there is no number, the next page is displayed.
Challenge 8.3 Further extend the book reader so that it can accept nega ve numbers for skipping pages.
Entering -1 should go back to the previous page. There are many ways to achieve this.
Tes ng, Tes ng
9
Self-review 9.4 What is uni est? uni est is the module name for
PyUnit.
It means that the class Fibonacci_Test is a subclass of uni est.TestCase ans will be a class containing unit tests to be
executed as and when.
It is asser ng that the result of execu ng fibonacci ( 10 ) should be the value 55. The unit test only succeeds if this
is the case.
Self-review 9.9 What do ‘Red’ and ‘Green’ mean in the context of unit tes ng? ‘Red’ means that the test has failed,
i.e. one or more of the test methods failed. ‘Green’ means that all the test methods passed and the test passed.
Self-review 9.10 Why are the terms ‘Red’ and ‘Green’ used in the context of unit tes ng?
Tes ng, Tes ng
Because in tools origina ng with sUnit and JUnit, red was used to indicate a failed test and green used for a non-
failing test. This tradi on is con nued in Eclipse tools for JUnit and TestNG with Java and PyDev with Python.
Self-review 9.14 Using the Web, look up the term eXtreme programming, which has been men oned in this chapter.
What are the main features of this method and how does unit tes ng fit into it?
Self-review 9.15 Debugging code thoroughly usually gives rise to a few excep ons. To debug code efficiently, it’s
important that you understand what Python’s different excep on types mean. What are the
following excep ons used for in Python:
• Asser onError
• ImportError
• IndexError
• KeyError
• NameError
• TypeError
• ValueError
Programming Exercises
Exercise 9.1 Although much of this chapter has been about tes ng, another fundamental skill is being able to iden fy
and correct errors once your tes ng has uncovered them. The following pieces of code all contain
simple errors. Iden fy the errors in each program and suggest possible tests to detect them and
solu ons to fix them:
1. for i in range(1, -10, 1):
print i
2. l = [1, 2, 3, 4, 5]
l[6] = 6
Exercise 9.2 Complete the Matrix class test by adding test methods to deal with the subtrac on and
mul plica on opera ons.
Exercise 9.3 Write a test program for the queue implementa on from Sec on ??
(page ??).
import sys
sys.path.append ( ’../../../SourceCode/classyObjects’ )
Exercise 9.4 Write a test program for the stack implementa on from Sec on ?? (page ??).
Exercise 9.5 Write a test program for the Account class from Exercise 6.6 (page 49), the CreditAccount class from
Exercise 7.2 (page 56), and the StudentAccount class from Exercise 7.3 (page 56).
Exercise 9.6 Below is the start of a test suite; the exercise is to write a module that passes it. Your code will provide
func ons to calculate various sorts of average on lists of data:
if __name__ == ’__main__’:
uni est.main ( )
Exercise 9.7 The test suite for the previous task is a good start, but not very complete. Add some more test cases. In
par cular, you should test for:
• randint
• random
• choice
Exercise 9.9 If you have completed the exercise above, you will have no ced that the random module contains both
func ons and classes. The classes represent various sorts of random number generator, and many of
the available func ons are duplicated as methods in each of the classes. Write a test suite to test the
randint, random and choice methods in the random.Random class.
Exercise 9.10 Some programs cannot be easily tested using unit test modules such as PyUnit. GUIs, in par cular,
need both unit tes ng (to exercise applica on logic) and tes ng that exercises the graphical
components of the program.
For this exercise you need to thoroughly test the Turtle module. Although you are already familiar
with this code, you should make sure that you plan your tes ng carefully and exercise as many of the
available func ons as possible. In par cular, you should note that many func ons in turtle are not
graphical, and so can be tested with PyUnit.
Tes ng, Tes ng
Exercise 9.11 Some data is more interes ng to test than others. UK postcodes (unlike US zip codes) are par cularly
interes ng because they have lots of special cases. Most postcodes consist of two le ers, one
number, a space, a number and two le ers. For example, James’ office postcode is CV1 5FB. However,
many postcodes are slightly different, such as PO10 0AB, SW1A 0AA and SAN TA1.
Read about Bri sh postcodes on Wikipedia h p://en.wikipedia.org/ wiki/UK_postcodes and write a table
of test data that would thoroughly exercise a postcode parser.
Challenges
Challenge 9.1 We le these ques ons as ques ons for the reader in Sec on ?? (page ??):
1. Should we be stopping numbers such as IIIIIIIIIIII, for example, from being legal?
2. Should we be forbidding mixed case numbers?
3. Are MCMIC, MCMXCIX and MIM all valid representa ons of 1999? Why does MCMXCIX appear to
be the preferred representa on?
4. Is MCMCXCVIII a valid representa on of 2098?
5. Is MXMVII a valid representa on of 1998?
Challenges 75
1. Should we be stopping numbers such as IIIIIIIIIIII, for example, from being legal?
2. Should we be forbidding mixed case numbers? (Probably yes.)
3. Are MCMIC, MCMXCIX and MIM all valid representa ons of 1999? Why does
MCMXCIX appear to be the preferred representa on?
4. Is MCMCXCVIII a valid representa on of 2098?
5. Is MXMVII a valid representa on of 1998?
Challenge 9.2 In this challenge you will be developing a program using Test-Driven Development
(TDD), which we introduced in Sec on ?? (page ??). Make sure you follow the
principles of TDD strictly. The purpose of this challenge is not just to give you more
programming prac ce, but to give you experience of developing a whole program
using TDD.
In Chapters 6 and 7 we developed the Die class and its various subclasses. For this
challenge you will write a game of Snap, which should be played on the console (i.e.
you don’t need to write a GUI unless you want to). You will probably want to include
the following components, but the detailed design of the code is up to you:
• A pack of cards. You will probably want to use a subclass of Die for this. You
don’t have to model a standard pack of 52 cards, it’s up to you.
• Some part of your program should control the game. This component should
be responsible for knowing whose turn it is to play and when the game has
been won (or drawn if you run out of cards).
• An interface. Some component of your program should be responsible for
communica ng with the user. Following good HCI principles, you should make
sure that the user is always aware of the state of the game (including their
score).
Note that because users are playing with a pack of cards, when one card is (randomly)
played, it cannot be used again. So you need some way to ensure that cards are not
played twice – perhaps by keeping track of which cards have already been played.
This code could be placed in various components of the program. Think about where
would be most sensible to put it (but remember, you can always refactor your code
later on).
Challenge 9.3 In Sec on ?? (page ??) of this chapter, we wrote a test class for the matrix module from
Sec on ?? (page ??). In this challenge we will give you code for another module that
uses matrices to perform some simple graphics opera ons. The code comes with
some simple tests, your job is to test the code thoroughly using PyUnit.
In graphics applica ons such as the GIMP or Photoshop and in anima ons, shapes
and objects are o en moved, scaled and rotated automa cally. This is o en done
using a technique called homogeneous coordinates, in which 3D matrices are used
to manipulate 2D images.
To convert a 2D point into a homogeneous 3D point we make the following transforma on:
(x,y)7→(x,y,1)
76 Tes ng, Tes ng
and to convert back to an ordinary 2D point the following transforma on needs to be performed:
To perform a transforma on (rota on, transla on or scaling) on a point, the point needs to be
mul plied by a transforma on matrix. In the code below we have created a class called HomogMatrix
which is a subclass of the Matrix class you have seen before. This class has methods to convert vectors
to and from their homogeneous counterparts. The module also has func ons to perform
transforma ons on vectors and code to draw shapes (made from lists of vectors) with the Python
turtle.
Make sure you spend some me looking through this code in order to understand it, before you begin
to write some test cases for the HomogMatrix class and the later func ons.
’’’Provides func ons to rotate, scale and translate points using homogeneous matrices.’’’
def scale ( v , ( sx , sy ) ) :
Challenges 77
if __name__ == ’__main__’:
# Test data -- some simple shapes made from lists of points.
# A point is a 2D vector [[x, y]] shapes = {
’square’ : [
HomogMatrix ( [ ( 0.0 , 0.0 ) ] ) ,
HomogMatrix ( [ ( 100.0 , 0.0 ) ] ) ,
HomogMatrix ( [ ( 100.0 , 100.0 ) ] ) ,
HomogMatrix ( [ ( 0.0 , 100.0 ) ] ) ,
HomogMatrix ( [ ( 0.0 , 0.0 ) ] ) ] ,
’rectangle’ : [
HomogMatrix ( [ ( 0.0 , 0.0 ) ] ) ,
HomogMatrix ( [ ( 200.0 , 0.0 ) ] ) ,
HomogMatrix ( [ ( 200.0 , 100.0 ) ] ) ,
HomogMatrix ( [ ( 0.0 , 100.0 ) ] ) ,
HomogMatrix ( [ ( 0.0 , 0.0 ) ] ) ] ,
’pentagon’ : [
HomogMatrix ( [ ( 0.0 , 0.0 ) ] ) ,
HomogMatrix ( [ ( 100.0 , 0.0 ) ] ) ,
HomogMatrix ( [ ( 131.0 , 95.0 ) ] ) ,
HomogMatrix ( [ ( 50.0 , 154.0 ) ] ) ,
HomogMatrix ( [ ( -30.0 , 95.0 ) ] ) ,
HomogMatrix ( [ ( 0.0 , 0.0 ) ] ) ]
}
for shape in shapes.keys ( ) : print shape , ’:’ for vector in
shapes[shape] :
print vector
draw ( shapes[shape] ) print
ss = map ( lambda v : trans ( v , data ) , shapes[s] ) print t , s , ’:’ for v in ss : print ’\t’
, v print draw ( ss )
Self-review 10.1 Why are data structures other than sequence and dic onary useful?
Because they have proper es that are different and many algorithms need data structures that have proper es different
to those of sequence and dic onary.
Self-review 10.3 Why is it not always possible to use Binary Search for all searches in sequences?
Because the Binary Search algorithm requires the data in the sequence to be sorted.
Self-review 10.4 What alterna ves to sequence are there for storing data to be searched?
The data could be in a dic onary, in which case the search is O(1), or in a search tree in which case the performance is
O(log2n). Dic onaries are clearly the best solu on. The excep on is where the data has to be held in a sorted order.
The me complexity of ‘divide and conquer’ algorithms is invariably be er than any linear algorithm.
Binary Search (O(log2n)) is be er than Linear Search (O(n)). Quicksort and Merge Sort (O(nlog2n))
are be er (at least in general) than Bubble Sort (O(n2)).
Of course, ‘divide and conquer’ should not be used if ‘direct access’ (O(1)) methods are available. So
don’t use sequences if dic onaries can do the job.
Self-review 10.9 Why inves gate tree data structures at all when we have sequences and dic onaries?
Dic onaries are implemented using open hash tables which give fine performance but the data is
not stored in a sorted form. There are map-related algorithms that can happily suffer decreased
performance for access and update because the need is for the data to be sorted. For these
algorithms maps implemented using trees are very important.
Explain why in the first code sequence there is a change to the list referred to
by a when there is a change to b, but in the second code sequence there is not.
In the first code sequence a and b refer to the same list, i.e. the list object is shared by two variables.
In the second code sequence b refers to a different list object.
Self-review 10.11 Is an algorithm that has me complexity O(n) faster or slower that one that has
me complexity O(log2n)? How does a me complexity of O(nlog2n) compare
to them?
Self-review 10.12 In the recursive version of Quicksort, what are the base cases and recursive cases
of the algorithm?
Which of the figures below correctly represents trees constructed with this class?
Tree 1 Tree 2
Exercise 10.1 Extend the unit test program for tes ng the search func ons so that its coverage is far
be er.
Exercise 10.2 Extend the unit test program for tes ng the sort func ons so that its coverage is far be er.
Exercise 10.3 Create a quicker Quicksort by extending the implementa on in this chapter so that
Bubble Sort is used instead of a recursive call of Quicksort when the parameter is a
sequence with less than 10 items.
Exercise 10.4 Create an improved Quicksort implementa on by changing the algorithm for selec ng
the pivot so that the two sub-sequences created by the par on are approximately the
same length.
Exercise 10.5 This exercise is about using the ideas from the binary search algorithm to play a simple
“20 Ques ons” type game. The (human!) player thinks of a number between 0 and
100. The program asks the player a series of yes/no ques ons. The first ques on will
be “Is the number between 0 and 50?”, the rest follows the binary chop approach.
What is the maximum number of ques ons the program will have to ask the player in
order to obtain the correct answer?
Exercise 10.6 Different comparators can be used to sort different kinds of data. Write comparators
implemen ng the following comparisons and test them by using them to sort some
appropriate data:
1. A lexicographical comparator – i.e. one that compares two strings based on their
alphabe c ordering.
2. An ASCII comparator that can be used to sort characters based on their ASCII value.
Hint: remember the ord func on!
3. A comparator that can be used to sort names based on their surname. This
comparator should use strings of the form ’Sarah Mount’, ’James Shu leworth’,
’Russel Winder’, and ’James T Kirk’ and compare them alphabe cally on the last word
in the string.
86 Algorithms and Data Structures
Exercise 10.7 When deciding what sor ng algorithm to use on a list, it is useful to find out whether a
list is nearly sorted. There are several ways to do this. Write func ons which implement
the following measures – if any of the func ons return 0 the list is already sorted. Make
sure that you compare the different func ons on a range of sorted and unsorted data:
Exercise 10.8 In Sec on ?? we introduced the built-in class set which efficiently implements sets (using
hash tables). This class contains many useful set opera ons such as intersec on, union
and difference, but it does not have a Cartesian product (aka cross product) opera on.
The Cartesian product of two sets is the set of all pairs created by taking an item from
the first set and an item from the second set. For example if we have the set { 1 , 2 }
and the set { ’a’ , ’b’ } then the Cartesian product is the set { ( 1 , ’a’ ) , ( 1 , ’b’ ) , ( 2 , ’a’
) , ( 2 , ’b’ ) }.
For this exercise write a subclass of set that provides a method for calcula ng Cartesian
products.
Exercise 10.9 Subclass the OrderedBinaryTree class from Sec on ?? to create a class that has a method
reflect which exchanges the le and right subtrees of each branch, like this:
Exercise 10.10 The meit module can be used to me the execu on of code. For example, the
following interpreter session shows that the built-in sort method for Python lists takes
1 s to sort the list [ 1 , 2 , 3 , 4 , 5 ] one million mes on the machine we tried it on:
>>> import meit
>>> t = meit.Timer ( stmt = ’[ 1 , 2 , 3 , 4 , 5 ].sort ( )’ )
>>> t. meit ( 1000000 ) # Run the statement 1000000 mes.
0.99292302131652832
>>>
Use meit to compare how long the various sor ng algorithms covered in this chapter
take to sort a given list.
Challenges 87
Challenges
Challenge 10.1 Create a type that has the same methods as a dic onary but which uses an ordered binary
tree to store the data.
Inser on Sort
Shell Sort
Heapsort
Radix Sort
Research these algorithms, extend the unit test program to test implementa ons of
these algorithms, then add implementa ons of these algorithms.
Threading the Code
11
Self-review 11.1 What is a ’thread’ and what is a ’process’? What is the difference between the two?
Self-review 11.2 What does the ’scheduler’ in an opera ng system take responsibility for?
Self-review 11.4 Threading is used extensively in interac ve programming in applica ons such as games, GUIs, Web
browsers, and so on. Why is threading so important for programs that need to interact with humans?
if __name__ == ’__main__’ :
pool = [ Foobar ( ) for i in range ( 10 ) ] map ( lambda t : t.start ( ) , pool )
Self-review 11.6 On one occasion when we ran the code above, we got the following output:
Thread-1
Thread-2
Thread-7
Thread-3
90 Threading the Code
Thread-9
Thread-8
Thread-6
Thread-10
Thread-4
Thread-5
Why don’t the numbers appear sequen ally?
Self-review 11.7 To the nearest second, how long will the code in Self-review 11.5 take to
execute?
Self-review 11.8 The second threaded guessing game program can take up to 5 s to terminate
a er the user has entered Ctlr+d. Why is this?
When the user presses Ctrl+d, the main thread sets the keepGoing variable in the generator
thread to False and then terminates. The generator thread could just have tested the value
and entered a sleep of up to 5 s. Only then will it see the changed value, terminate the
loop, terminate the run method and hence terminate.
Self-review 11.9 ’Livelock’ and ’deadlock’ are two problems that are commonly associated with mul -
threaded programs. Define ’deadlock’ and
’livelock’.
Self-review 11.13 Why must the run method be overridden in subclasses of threading.Thread?
What output would it give if used outside a thread object, like this:
if __name__ == ’__main__’:
print threading.currentThread()
Self-review 11.15 Imagine you are wri ng a mul -player game. Your game will have some
interes ng graphics that need to be generated quickly to provide a
smooth anima on. There will be a sound track to the game-play and
several players will be interac ng at once. Inside the game there will be
both player and non-player characters. What parts of this program
would you want to separate out into their own threads?
Programming Exercises 91
Programming Exercises
Exercise 11.1 Write a program that creates two threads, each of which should sleep for a random
number of seconds, then print out a message which includes its thread ID.
Exercise 11.2 Star ng with your code from the previous exercise, add a counter to
your program. Each thread should include the value of the counter in the message it
prints to the screen and should increment the counter every me it wakes up. So, the
counter will hold the total number of messages printed to the screen by all the running
threads.
You will need to use some form of concurrency control to ensure that the value of the
counter is always correct. Several of these are available in Python. One simple solu on
is to use locks. The idea here is that if a variable is locked, it cannot be changed by code
in another thread un l it has been unlocked. In this way we can use locks to create
cri cal sec ons in our code.
Here’s a code fragment to get you started:
import threading
Exercise 11.3 Python provides a special data structure in a class called Queue.Queue that is specifically
for use in mul -threaded programs. You have already learned about queue types in
Sec ons ?? (page ??) and ?? (page ??). In Python’s queues, data can be added to a
queue using a method called put and removed from it using the method get. Here’s an
example:
Here we have added the objects 5 and 4 to a queue we have created, then retrieved
those two values. Note that we have called q.get a third me, even though the queue
is now empty. You might have expected Python to raise an excep on here, because we
tried to access a value that doesn’t exist. In fact, what is happening here is that Python
is wai ng (blocking) on the queue to provide a value. Because queues are expected to
be used in concurrent programs, the authors of the Queue.Queue class knew that
other threads might be placing data on the queue even when one thread is wai ng to
fetch data from it.
For this exercise, write a small program in which several threads access a single queue
at the same me. Each thread should randomly either place some random data on the
queue, or take data off it. Make sure you print out lots of useful informa on about
what each thread is doing to the queue so you can watch how the program proceeds!
Challenges
Challenge 11.1 Tkinter provides a number of methods to control concurrency and scheduling in GUIs,
including:
• widget.a er
• widget.update
• widget.wait_visibility
Read the Tkinter documenta on to find out what these methods do.
Start out by crea ng a simple GUI that implements an alarm. To help with this,
Tkinter bu ons have methods called bell and flash that ’beep’ and make the bu on
flash, respec vely. Use the a er method to schedule an alarm to sound a er a given
number of milliseconds. Make sure the user has a way of turning the alarm off!
When you have a basic alarm program working, implement the following
improvements:
Challenge 11.2 The classic problem in the area of concurrent programming, was proposed by Edsgar
Dijkstra in 1971, and recast by Tony Hoare as the The Dining Philosophers Problem.
Five philosophers are si ng at a round table. Philosophers are quite eccentric, all
they do all day is think and eat, but they can’t
Challenges 93
do both at once. Between each pair of philosophers is a fork and each philosopher needs two forks to
eat. What would happen if all the philosophers organize themselves to pick up their le fork and then
their right fork whenever they stop thinking? Can you think of a be er way for philosophers to eat?
Research this problem and write a program that uses threads to represent each philosopher to explore how to
avoid deadlock.
The Life of the Game
12
Self-review 12.1 Why did we create a class for this applica on rather than just leave it as a set of func ons in
a module? Is this actually needed?
Self-review 12.2 What do the terms event, event handler and event loop mean.
Self-review 12.3 Which are the event handler/callback methods in the Life class?
Self-review 12.4 Why have we used mul ple threads in this program?
Self-review 12.5 What is the reason for changing from using a list of list of Booleans as the representa on of
the state of the universe?
Self-review 12.6 Why have bu ons been used to present the cells of the game universe?
Self-review 12.9 What was the run- me error that had to be avoided in Sec on ??? Why did it need to be
avoided?
Self-review 12.11 The Game of Life has many stable pa erns. In the text, we men oned Block, Boat and Blinker.
Other stable shapes are Toad, Glider and Lightweight Spaceship (LWSS). What are these
shapes and why are they stable?
Hint: The answer to the ques on isn’t in this book. You will need to research another sources.
Self-review 12.12 What are observer variables and how are they used in GUIs?
The Life of the Game
Self-review 12.15 We’ve said that the universe which starts off with no life is stable. What
would happen if we started the game with every cell being live?
Programming Exercises
Exercise 12.1 Extend the test program for the Game of Life code to include Toad, Glider and
LWSS as part of the test.
Exercise 12.2 Extend the test program for the Game of Life code to include Gosper’s Gliding
Gun as part of the test.
Exercise 12.3 Amend the Game of Life program to use an icon rather than # as the displayed
symbol.
Exercise 12.4 HighLife is a varia on on Conway’s Game of Life. Instead of the 23/3 rule (a live
cell stays alive only if it has two or three neighbors otherwise it dies, and dead
cell is made live if it has exactly three live neighbors), HighLife uses the 23/36
rule (a live cell stays alive only if it has two or three neighbors otherwise it
dies, and dead cells become alive if they have either three or six live
neighbors). Create a version of the Game of Life program that uses the
HighLife rules.
Exercise 12.5 As presented in this chapter, the user can use the Game of Life GUI to populate
the universe randomly. Add a list box which gives the user op ons to try out
the Block, Boat and Blinker socie es.
Hint: Storing these socie es as lists in the program should make things
straigh orward.
Exercise 12.6 In the exercise above, you allowed the user to try out some preselected
socie es. Storing the socie es as data structures in the code makes it difficult
to extend the range of possibili es. For this exercise extend the program so
that the socie es are stored in files that are read in when the program starts.
The list box of possible socie es for the user to try should be calculated from
the files that were read in and not predefined.
Exercise 12.7 Add the func onality to the Game of Life program of allowing users to store
the current game state in a file, and to reload it when they next start the
program.
Challenges 97
Exercise 12.8 The Game of Life program in this chapter is an example of a program which
can have mul ple user interfaces – in this case, one on the console and a
GUI. This exercise is to write a program that implement the Caesar Cipher
from Sec on ?? (page ??) but which has mul ple user interfaces. The
program should have two interfaces to the cipher – one using the console
and one which is a GUI.
Hint: Make sure that the GUI classes, the classes to control console
interac on and the actual cipher are all separate. This will mean that
you should be able to swap between the two interfaces and add new
ones without changing the Caesar Cipher.
Challenges
Challenge 12.1 Inves gate the technique of using mock objects to help test the user interface.
Challenge 12.2 Create a class called LifeCell that removes the need for dealing directly with
StringVars and bu on construc on (for the grid, anyway). That is,
something that can be used to set state (cella.makeAlive, or
cella.setState(True), perhaps) and expose an associated bu on for adding
to the GUI (cella.getBu on might be appropriate).
Challenge 12.3 Exercise 12.4 introduces the HighLife rules and a simple nota on for rules
for this kind of cellular automata. The standard Game of Life is described
in this nota on as 23/3, whilst HighLife is described as 23/36. Modify the
program so that the rule is set by the user by entering two sequences of
numbers into two text boxes.
When your new version of the game is working, enter the rule in the image
above. Try it on a single live cell.
Challenge 12.4 Sudoku is a popular single-player puzzle game played on a 9×9 grid (see
the example below). The object of the game is to fill every square with a
digit from 1–9 such that each row and column contains exactly one
instance of each digit, as does every 3×3 square.
5 3 7
6 1 9 5
9 8 6
8 6 3
4 8 3 1
7 2 6
6 2 8
4 1 9 5
8 7 9
be sensible to download a set of puzzles and solu ons from a free online
source rather than making your own in the first instance. Doing random
crea on of puzzles is a natural evolu on of the program. From a usability
point of view being able to pause a game and restart it later part solved is
a good idea so storing puzzles and solu ons in a sensible format that you
can easily parse is an important part of the solu on.
Wikipedia has a good ar cle on Sudoku at h p://en.wikipedia.org/ Sudoku.
PyGames
13
Self-review 13.2 What is ‘bli ng’? Why is it important for anima on?
Self-review 13.4 What is the difference between the Rect.move and Rect.move_ip methods in the
pygame.Rect class? Give two examples of how these methods can be used in a line of code.
Self-review 13.5 Most programs that manipulate images and anima ons put the origin, (0, 0), of the screen at
the top-le hand corner of the applica on window. Why is this?
Self-review 13.7 In the Snake game, what did the following names represent and what are they used for:
clock frame SnakePart.UP fps dirty body bodysprite
Self-review 13.8 What does the pygame.Surface.convert do? Why did we use it in our code?
Self-review 13.10 What is the difference between a KEYDOWN and a KEYUP event?
Self-review 13.11 What names in pygame.locals are used to represent the following keys on the keyboard:
q Enter Shi Tab Space
PyGames
Self-review 13.12 How can we find the current posi on of the mouse when using PyGame?
Self-review 13.15 What does the pygame.Sprite.update method do? Why is it usually
overridden in subclasses?
Self-review 13.16 Briefly describe the technique of ‘dirty rect anima on’. Why is it more
efficient than other methods?
Self-review 13.17 What is a ‘blit buffer’? What name did we give the blit buffer in the Snake
code in Sec on ???
Programming Exercises
Exercise 13.1 Change the bouncing ball anima on so that the anima on begins with the ball
in a random posi on on the screen.
Exercise 13.2 The speed at which the ball travels will make a big difference to how smooth
the anima on looks. Allow the user to vary the speed of the anima on by
using the ‘up’ and ‘down’ arrow keys on the keyboard. Experiment with
different speeds – which looks best?
Exercise 13.3 Add another ball to the bouncing ball anima on and have them both begin in
random posi ons.
Exercise 13.4 Having completed the previous exercise, make sure that the two balls bounce
off each other whenever they collide.
Exercise 13.5 Write a simple demonstra on program to show how PyGame allocates numbers
(scancodes) to different keys on the keyboard. You should start with a blank
screen, and whenever the user presses a key, display its scancode (which you
can get from event.key).
Exercise 13.6 Write a PyGame program to simulate an Etch A Sketch. The user should be able
to use the arrow keys on the keyboard to draw a con nuous line on a blank
screen.
Hint: Look in the pygame.draw module. What does the aa mean in the name
pygame.draw.aaline?
Challenges 101
Exercise 13.7 The Bouncing Ball anima on has almost everything necessary to create a
game of single-player Pong, except a bat. Add a new subclass of Sprite to
represent the bat, and make sure that the ball collides correctly with it.
Use the display_score func on in the game_func ons module to display
the score (which should increment every me the ball hits the bat).
Hint: You might want to make the ball a Sprite too, to make collision detec on
easier.
Exercise 13.8 Change the Snake program so that the snake only grows in length when the
head collides with randomly placed sprites (snake food), which should be
the same size as a SnakePart. Make sure that a er a random period, new
food is made available to the snake.
Exercise 13.9 Augment the game_func ons module with a high score table. Use either the
shelve or pickle module to store the scores.
Exercise 13.10 Add a second snake to the Snake game that is controlled by the computer.
This second snake should move in random direc ons around the screen.
If the player’s snake collides with the computer’s, the player loses the
game. Allow the computer’s snake to eat food too – preven ng the
player’s snake from gaining valuable points!
Exercise 13.11 Add ‘lives’ to the Snake game. The player should lose a life if the snake
collides with itself or the sides of the screen, but only lose the game when
all the player’s lives are exhausted. Make sure that the player is always
aware of how many lives they have le .
Hint: Think about which parts of your code should go in the snake.py file and
which should go in the game_func ons module.
Challenges
Challenge 13.1 Implement a single-player Space Invaders arcade game (see Space
Invaders on Wikipedia for a descrip on: h p://en.wikipedia.org/
wiki/Space_Invaders).
Hint: You should start by crea ng a game with a single level. Then you can
evolve this to a mul -level game, for which you will probably want
to write code to use configura on files to describe what should
happen on each level.
You should create any images and sounds you need to use in the
game. We recommend GIMP (h p://www.gimp.org/) or Inkscape
(h p://www.inkscape.org) for graphics.
Challenge 13.2 Python can run on a variety of devices apart from PCs. These include PDAs,
embedded computers and mobile phones. Any Linux or Symbian based
phone should be able to run Python: the phone
PyGames