PC-204 – Introduction to
Write a function
sphere_volume that returns the volume
of a sphere when given radius
r as a parameter.
Then write a main program that calls
print the volume of a sphere with a radius of 5.
or the main program?
Each function should take two parameters,
divisor, and return the remainder.
We should be able to use these functions interchangeably since
passing the same parameters to each should result in the same answer.
Assume that both parameters are integers.
To demonstrate correctness, write a main program that calls all
three functions with the same arguments, e.g., 10 and 4,
and print the results.
print_rangethat prints the range of numbers from
endare integer parameters to the function. Your code should work whether
startis larger or smaller than
Write a test program that uses
input to ask
the user to enter the starting and ending numbers and call
print_range with those arguments.
The greatest common divisor (GCD) of a and b is the largest number that divides both of them with no remainder.
One way to find the GCD of two numbers is Euclid's algorithm, which is based on the observation that if r is the remainder when a is divided by b, then gcd(a, b) = gcd(b, r). As a base case, we can use gcd(a, 0) = a.
Write a recursive function called
gcd that takes
returns their greatest common divisor.
You can assume that both
are positive integers. Make sure your code is written such
gcd(a, b) == gcd(b, a). Of course also include
test code that calls your gcd function to demonstrate that
the results are correct.
If you need help with the algorithm, see
Demonstrate that your function works properly by writing
a main program that prints the results from
for integer pairs such as (12, 8) and (20, 24).
Credit: This exercise is based on an example from Abelson and Sussman's “Structure and Interpretation of Computer Programs”.
Here is a loop that starts with an initial estimate of the square
x, and improves it until
it stops changing:
while True: y = (x + a / x) / 2 if abs(y - x) < epsilon: break x = y
epsilon has a value like 0.0000001 that determines
how close is close enough.
Encapsulate this loop in a function called
a as a parameter, chooses a reasonable value of
x, and returns an estimate of the square root of
To test the square root algorithm in this chapter, you could compare
math.sqrt. Write a function named
test_square_root that prints a table like this:
1.0 1.0 1.0 0.0 2.0 1.41421356237 1.41421356237 2.22044604925e-16 3.0 1.73205080757 1.73205080757 0.0 4.0 2.0 2.0 0.0 5.0 2.2360679775 2.2360679775 0.0 6.0 2.44948974278 2.44948974278 0.0 7.0 2.64575131106 2.64575131106 0.0 8.0 2.82842712475 2.82842712475 4.4408920985e-16 9.0 3.0 3.0 0.0
The first column is a number, a; the second column is the square
root of a computed with the [your function]; the third
column is the square root computed by
the fourth column is the absolute value of the difference between
the two estimates.
ATOMrecords. A PDB consists of lines (records) that start with the record type, such as
ATOM, followed by data associated with the record. An
ATOMrecord looks like the first line below. The second and third lines are there to facilitate column numbering.
ATOM 4 O ALA A 1 43.328 45.046 -13.879 1.00 54.88 O 12345678901234567890123456789012345678901234567890123456789012345678901234567890 1 2 3 4 5 6 7 8
If we number columns starting from 1, then the x, y and z coordinates
of the atom are in columns 31-38, 39-46 and 47-54, respectively. In
the example above, the coordinates are (43.328, 45.046, -13.879).
Because the fields are directly adjacent to each other, i.e.,
there is no guarantee that there is whitespace between the coordinates,
you should not use the
split method for strings
(which depends on whitespace) to divide up the line.
Write a function
average_coord, which takes the name of a file
as its only parameter, that:
requestsmodule that will handle the binary-to-string conversion automatically. However, for this assignment, you can use the following code:
def open_pdb(code): url = "https://files.rcsb.org/view/%s.pdb" % code import urllib.request, io return io.TextIOWrapper(urllib.request.urlopen(url))You can treat the return value from
fileobject. For example, with the following code, you can open a PDB entry and read all records in the entry:
f = open_pdb("3FX2") for record in f: print(record) f.close()
ATOMrecords and their average coordinates. (To clarify, the output should have exactly four numbers: the number of
ATOMrecords processed, the average x coordinate for all
ATOMrecords, the average y coordinate for all
ATOMrecords, and the average z coordinate for all
ATOMrecords, i.e., the output is not the average of the x, y and z coordinates for each
For your test data, use the PDB entry 3FX2. The average x coordinate should be around 21.83.
The first version of the function,
has_dups, may use any data
structure (lists, dictionaries, sets), while the second version,
has_dups_list, may not use either dictionaries or sets. Test
your functions using both lists with and without duplicates.
Use the following timing function to check which version runs faster:
def timing(func, argument, repeat=1000): import time total = 0.0 for i in range(repeat): start = time.time() func(argument) total += time.time() - start print "Average time (ms):", total / repeat * 1000.0 timing(has_dups, test_list) timing(has_dups_list, test_list)
You should use a variety of test lists. For example, how do these test data differ in run time for the two functions:
test_list = list(range(1000)) test_list = list(range(1000)) ; test_list[-1] = test_list test_list = list(range(1000)) ; test_list = test_list
Here's another Car Talk Puzzler (http://www.cartalk.com/content/puzzlers):
"What is the longest English word, that remains a valid English word, as you remove its letters one at a time?
"Now, letters can be removed from either end, or the middle, but you can't rearrange any of the letters. Every time you drop a letter, you wind up with another English word. If you do that, you're eventually going to wind up with one letter and that too is going to be an English word - one that's found in the dictionary. I want to know what's the longest word and how many letters does it have?
"I'm going to give you a little modest example: Sprite. Ok? You start off with sprite, you take a letter off, one from the interior of the word, take the r away, and we're left with the word spite, then we take the e off the end, we're left with spit, we take the s off, we're left with pit, it, and I."
Write a program to find all words that can be reduced in this way, and then find the longest one. This exercise is a little more challenging than most, so here are some suggestions:
walkthan the code in Chapter 14 of Think Python 2e. Write a function,
count_extensions, that traverses a given directory and subdirectories and counts the number of files of each suffix type, e.g.,
The documentation for splitting a filename into a base name and an extension may be found at http://docs.python.org/2/library/os.path.html#os.path.splitext.
Write a function,
get_pdb_ligands, which takes a PDB code
as parameter and returns a list of the ligands found in the entry.
The URL for this query has the form:
In this example,
4HHB is the 4-letter code for a PDB entry of
a “crystal structure of human deoxyhaemoglobin”. The returned
results from this query is in XML format and looks like:
<?xml version="1.0" encoding="windows-1252" standalone="no"?> <structureId id="4HHB"> <ligandInfo> <ligand structureId="4HHB" chemicalID="HEM" type="non-polymer" molecularWeight="616.487"> <chemicalName>PROTOPORPHYRIN IX CONTAINING FE</chemicalName> <formula>C34 H32 FE N4 O4</formula> <InChIKey>FEDYMSUPMFCVOD-UJJXFSCMSA-N</InChIKey> <InChI>InChI=1S/C34H34N4O4/c1-7-21-17(3)25-13-26-19(5)23(9-11-33(39)40)31(37-26)16-32-24(10-12-34(41)42)20(6)28(38-32)15-30-22(8-2)18(4)27(36-30)14-29(21)35-25/h7-8,13-16,36-37H,1-2,9-12H2,3-6H3,(H,39,40)(H,41,42)/b25-13-,26-13-,27-14-,28-15-,29-14-,30-15-,31-16-,32-16-</InChI> <smiles>Cc1c2/cc/3\nc(/cc\4/c(c(/c(/[nH]4)c/c5n/c(c\c(c1CCC(=O)O)[nH]2)/C(=C5C)CCC(=O)O)C=C)C)C(=C3C)C=C</smiles> </ligand> <ligand structureId="4HHB" chemicalID="PO4" type="non-polymer" molecularWeight="94.971"> <chemicalName>PHOSPHATE ION</chemicalName> <formula>O4 P -3</formula> <InChIKey>NBIIXXVUZAFLBC-UHFFFAOYSA-K</InChIKey> <InChI>InChI=1S/H3O4P/c1-5(2,3)4/h(H3,1,2,3,4)/p-3</InChI> <smiles>[O-]P(=O)([O-])[O-]</smiles> </ligand> </ligandInfo> </structureId>
The data of interest are the text that appear betweeen the
tags. Normally, the XML results are processed using
Python packages such as
minidom; for this exercise,
assume that the tags and data will appear on a single line and use
string operations to extract the information.
To retrieve data from an URL, use the
The following example will retrieve and print data from an URL.
# Python 2 import urllib with urllib.urlopen(url) as f: for line in f: print line # Python 3 import urllib.request, io with io.TextIOWrapper(urllib.request.urlopen(url)) as f: # Decode binary data to text assuming UTF-8 character encoding for line in f: print(line)
For testing, the input parameter for
should be the string
"4HHB" and the return value should
be a list of two strings:
"PROTOPORPHYRIN IX CONTAINING FE" and
(If you are ambitious, try using
minidom to extract the data.
Your code may look something like:
# Python 2 import urllib, xml.dom.minidom with urllib.urlopen(url) as f: dom = xml.dom.minidom.parse(f) [... your code for processing the dom goes here ...] # Python 3 import urllib.request, xml.dom.minidom with urllib.request.urlopen(url) as f: dom = xml.dom.minidom.parse(f) [... your code for processing the dom goes here ...]
The example towards the end of
Python 2: http://docs.python.org/2/library/xml.dom.minidom.html,
Python 3: http://docs.python.org/3/library/xml.dom.minidom.html, should help.)
- Input parameters:
Return value: instance of Rectangle
Operation: create a new instance of Rectangle
- Input parameter:
Return value: string
Operation: convert given Rectangle instance into string of form
(x, y, width, height)
- Input parameters:
Return value: None
Operation: change the x and y coordinates of the given Rectangle instance
- Input parameters:
Return value: instance of Rectangle
Operation: create a new Rectangle instance which is offset from the given instance in x and y coordinates by
Test your functions with the following code:
r1 = create_rectangle(10, 20, 30, 40) print str_rectangle(r1) shift_rectangle(r1, -10, -20) print str_rectangle(r1) r2 = offset_rectangle(r1, 100, 100) print str_rectangle(r1) # should be same as previous print str_rectangle(r2)
area_difference, that takes two Rectangle instances as parameters and returns the signed difference in area between them. "signed difference" means that rather than always returning a positive number, the sign of the return value should be negative if the first rectangle is smaller. Test your code with:
r1 = create_rectangle(10, 20, 10, 10) r2 = create_rectangle(20, 50, 15, 20) print area_difference(r1, r2)
offset_rectangleare renamed as
offset, respectively, and become methods of the class (so that the
rectargument to the functions become the
selfargument to the method).
Test your new class with the following code:
r1 = Rectangle(10, 20, 30, 40) print r1 r1.shift(-10, -20) print r1 r2 = r1.offset(100, 100) print r1 print r2
__add__method for the rectangle class that returns the
sumof two rectangles as a new rectangle which is the smallest rectangle that encloses the two input rectangles. Test your code with:
r1 = Rectangle(10, 20, 10, 10) r2 = Rectangle(20, 50, 15, 20) print r1 + r2
The answer should be
(10, 20, 25, 50).
The following are the possible hands in poker, in increasing order of value (and decreasing order of probability):
The goal of these exercises is to estimate the probability of drawing these various hands.
PokerHand.py, it deals seven 7-card poker hands and checks to see if any of them contains a flush. Read this code carefully before you go on.
has_twopair, etc. that return
Falseaccording to whether or not the hand meets the relevant criteria. Your code should work correctly for “hands” that contain any number of cards (although 5 and 7 are the most common sizes).
classifythat figures out the highest-value classification for a hand and sets the
labelattribute accordingly. For example, a 7-card hand might contain a flush and a pair; it should be labeled “flush”.
Gomoku is an abstract strategy board game. Also called Gobang or Five in a Row, it is traditionally played with Go pieces (black and white stones) on a go board with 19x19 intersections; however, because once placed, pieces are not moved or removed from the board, gomoku may also be played as a paper and pencil game. This game is known in several countries under different names.
Black plays first, and players alternate in placing a stone of their color on an empty intersection. The winner is the first player to get an unbroken row of five stones horizontally, vertically, or diagonally.
Your program should display the gomoku board and let players alternately select empty intersections by clicking on the canvas. Each click should result in a stone being placed on the board. The program should detect when a player wins and ask whether to start a new game.
For your implementation, use a Tkinter
to display the board. For this exercise, specify the width and
height of the canvas so that you can easily compute the coordinates
for the board lines and stones; for example, using a 380x380 canvas
for a 19x19 board would greatly simplify the convertion from pixels
to row and column indices. The lines of the board may be drawn using
create_line and the stones using
create_oval while specifying the
attribute for the color of the stones. To handle user interactions,
you will need to
bind an event handler to the canvas
instance to get mouse clicks.
The event instance that your handler receives as its argument will
y attributes for the position
of the mouse click; these attribute units are in pixels, so
you will need to convert them into board row and column indices.
For more information on how to use the Tkinter, see An Introduction to Tkinter (Work in Progress) by Fredrik Lundh.
(If you are ambitious, write your program so that the canvas
may be resized. You will need to bind to
events to receive notification when the canvas changes size, and
your board-to-pixel conversion factors will need to be updated
each time the board size changes.)