Week 1: Sep 6-10 (Python intro)
1.1 Become familiar with electronic Python documentation
1.2 Extend Exercise 1.1 with a loop
1.3 Find five errors in a script
1.4 Basic use of control structures
Week 2: Sep 13-17 (Python tasks)
2.1 Combine two-column data files to a multi-column file
2.2 Annotate a filename with the current date
2.3 Make a specialized sort function
Week 3: Sep 20-24 (Python tasks)
3.1 Find the paths to a collection of programs
3.2 Find old and large files in a directory tree
3.3 Estimate the chance of an event in a dice game
3.4 Determine if you win or loose a hazard game
Week 4: Sep 27-Oct 1 (Regular expressions)
4.2 Find errors in regular expressions
4.3 Explain the behavior of regular expressions
4.4 Interpret a regex code and find programming errors
Week 5: Oct 11-15 (Regular expressions, Python tasks)
5.1 Generate data from a user-supplied formula
5.2 Write an improved function for joining strings
5.3 Use tools to document a script
5.4 Prefix name of digital image files with date and time
Week 6: Oct 18-22 (Class exercises, Python tasks)
6.1 Implement a class for vectors in 3D
6.2 Extend the class from Exericse 6.1
6.3 Vectorize a constant function
6.4 Vectorize a numerical integration rule
6.5 Automate the creation of runtime examples
Week 7: Oct 25-29 (Class exercises, Python tasks)
7.1 Make a class for sparse vectors
7.2 Assignment and in-place modifications of NumPy arrays
7.3 Implement Exercise 3.3 using NumPy arrays
7.4 Implement Exercise 3.4 using NumPy arrays
7.5 Process comma-separated numbers in a file
Week 8: Nov 1-5 (Class exercises, Python tasks)
8.1 Matrix-vector multiply with NumPy arrays
8.2 Replace lists by NumPy arrays
8.3 Equip class Grid2D with subscripting
8.4 Extend the functionality of class Grid2D
Week 9: Nov 8-12 (Python tasks)
9.1 Investigate the efficiency of various DAXPY implementations
9.2 Investigate the efficiency of various DAXPY implementations cont.
9.3 Apply SWIG to an array class in C++
Week 1: Sep 6-10 (Python intro)
1.1 Become familiar with electronic Python documentation
Write a script that prints a uniformly distributed random number between -1 and 1 on the screen. The number should be written with four decimals as implied by the %.4f format.
To create the script file, you can use a standard editor such as Emacs or Vim on Unix-like systems. On Windows you must use an editor for pure text files - Notepad is a possibility, but I prefer to use Emacs or the ``IDLE'' editor that comes with Python (you usually find IDLE on the start menu, choose File--New Window to open up the editor). IDLE supports standard key bindings from Unix, Windows, or Mac (choose Options--Configure IDLE... and Keys to get a menu where you can choose between the three classes of key bindings).
The standard Python module for generation of uniform random numbers is called random. To figure out how to use this module, you can look up the description of the module in the Python Library Reference. Load the file $scripting/doc.html into a Web browser and click on the link Python Library Reference: Index. You will then see the index of Python functions, modules, data structures, etc. Find the item random (standard module) in the index and follow the link. This will bring you to the manual page for the random module. In the bottom part of this page you will find information about functions for drawing random numbers from various distributions (do not use the classes in the module, use plain functions). Also apply pydoc to look up documentation of the random module: just write pydoc random on the command line.
Name of scriptfile: printrandom.py (exercise class: Python)
1.2 Extend Exercise 1.1 with a loop
Extend the script from Exercise 1.1 such that you draw n random uniformly distributed numbers, where n is given on the command line, and compute the average of these numbers.
Name of scriptfile: averagerandom.py (exercise class: Python)
1.3 Find five errors in a script
Consider the following Python code:
#!/usr/bin/ env python import sys, random def compute(n): i = 0; s = 0 while i <= n: s += random.random() i += 1 return s/n n = sys.argv[1] print 'the average of %d random numbers is %g" % (n, compute(n))
There are five errors in this file - find them!
Name of scriptfile: averagerandom2.py (exercise class: Python)
1.4 Basic use of control structures
To get some hands-on experience with writing basic control structures in Python, we consider an extension of the Scientific Hello World script hw.py from Chapter 2.1 in the book (see also the lecture notes). The script is now supposed to read an arbitrary number of command-line arguments and write the sine of each number to the screen. Let the name of the new script be hw2a.py. As an example, we can write
python hw2a.py 1.4 -0.1 4 99
and the program writes out
Hello, World! sin(1.4)=0.98545 sin(-0.1)=-0.0998334 sin(4)=-0.756802 sin(99)=-0.999207
Traverse the command-line arguments using a for loop. The complete list of the command-line arguments can be written sys.argv[1:] (i.e., the entries in sys.argv, starting with index 1 and ending with the last valid index). The for loop can then be written as for r in sys.argv[1:].
Make an alternative script, hw2b.py, where a while loop construction is used for handling each number on the command line.
In a third version of the script, hw2c.py, you should take the natural logarithm of the numbers on the command line. Look up the documentation of the math module in the Python Library Reference to see how to compute the natural logarithm of a number. Include an if test to ensure that you only take the logarithm of positive numbers. Running, for instance,
python hw2c.py 1.4 -0.1 4 99
should give this output:
Hello, World! ln(1.4)=0.336472 ln(-0.1) is illegal ln(4)=1.38629 ln(99)=4.59512
Name of scriptfiles: hw2a.py, hw2b.py, hw2c.py (exercise class: Python)
Week 2: Sep 13-17 (Python tasks)
2.1 Combine two-column data files to a multi-column file
Write a script inverseconvert.py that performs the 'inverse process' of the following script:
#!/usr/bin/env python import sys, math, string usage = 'Usage: %s infile' % sys.argv[0] try: infilename = sys.argv[1] except: print usage; sys.exit(1) ifile = open(infilename, 'r') # open file for reading # read first comment line (no further use of it here): line = ifile.readline() # next line contains the increment in t values: dt = float(ifile.readline()) # next line contains the name of the curves: ynames = ifile.readline().split() # list of output files: outfiles = [] for name in ynames: outfiles.append(open(name + '.dat', 'w')) t = 0.0 # t value # read the rest of the file line by line: for line in ifile: yvalues = line.split() if len(yvalues) == 0: continue # skip blank lines for i in range(len(outfiles)): outfiles[i].write('%12g %12.5e\n' % \ (t, float(yvalues[i]))) t += dt for file in outfiles: file.close()
For example, if we first apply the script above to the specific test file:
some comment line 1.5 tmp-measurements tmp-model1 tmp-model2 0.0 0.1 1.0 0.1 0.1 0.188 0.2 0.2 0.25
we get three two-column files tmp-measurements.dat, tmp-model1.dat, and tmp-model2.dat. Running
python inverseconvert1.py outfile 1.5 \ tmp-measurements.dat tmp-model1.dat tmp-model2.dat
should in this case create a file outfile, which is almost identical to the test file above. Only the first line should differ (inverseconvert.py can write anything on the first line). For simplicity, we give the time step parameter explicitly as a command-line argument (it could also be found from the data in the files).
Hint: When parsing the command-line arguments, one needs to extract the name model1 from a filename model1.dat stored in a string (say) s. This can be done by s[:-4] (all characters in s except the last four ones). Chapter 3.4.5 describes some tools that allow for a more general solution to extracting the name of the time series from a filename.
Name of scriptfile: inverseconvert.py (exercise class: Python)
2.2 Annotate a filename with the current date
Write a function that adds the current date to a filename. For example, calling the function with the text myfile as argument results in the string myfile_Aug22_2010 being returned if the current date is August 22, 2010. Read about the time module in the Python Library Reference to see how information about the date can be obtained.
Name of scriptfile: add_date.py (exercise class: Python)
2.3 Make a specialized sort function
Suppose we have a script that performs numerous efficiency tests. The output from the script contains lots of information, but our purpose now is to extract information about the CPU time of each test and sort these CPU times. The output from the tests takes the following form:
... f95 -c -O0 versions/main_wIO.f F77WAVE.f f95 -o app -static main_wIO.o F77WAVE.o -lf2c app < input > tmp.out CPU-time: 255.97 f95 -O0 formatted I/O f95 -c -O1 versions/main_wIO.f F77WAVE.f f95 -o app -static main_wIO.o F77WAVE.o -lf2c app < input > tmp.out CPU-time: 252.47 f95 -O1 formatted I/O f95 -c -O2 versions/main_wIO.f F77WAVE.f f95 -o app -static main_wIO.o F77WAVE.o -lf2c app < input > tmp.out CPU-time: 252.40 f95 -O2 formatted I/O ...
First we need to extract the lines starting with CPU-time. Then we need to sort the extracted lines with respect to the CPU time, which is the number appearing in the second column. Write a script to accomplish this task. A suitable testfile with output from an efficiency test can be found here.
Hint: Find all lines with CPU time results by using a string comparison of the first 7 characters to detect the keyword CPU-time. Then write a tailored sort function for sorting two lines (extract the CPU time from the second column in both lines and compare the CPU times as floating-point numbers).
Name of scriptfile: ranking.py (exercise class: Python)
Week 3: Sep 20-24 (Python tasks)
3.1 Find the paths to a collection of programs
A script often makes use of other programs, and if these programs are not available on the computer system, the script will not work. This exercise shows how you can write a general function that tests whether the required tools are available or not. You can then terminate the script and notify to the user about the software packages that need to be installed.
The idea is to write a function findprograms that takes a list of program names as input and returns a dictionary with the program names as keys and the programs' complete paths on the current computer system as values. Search the directories in the PATH environment variable for the desired programs (see Chapter 3.2.5). Allow a list of additional directories to search in as an optional argument to the function. Programs that are not found should have the value None in the returned dictionary.
Here is an illustrative example of using findprograms to test for the existence of some utility programs used in the course:
programs = { 'gnuplot' : 'plotting program', 'gs' : 'ghostscript, ps/pdf interpreter and previewer', 'f2py' : 'generator for Python interfaces to F77', 'swig' : 'generator for Python interfaces to C/C++', 'convert' : 'image conversion, part of the ImageMagick package', } installed = findprograms(programs.keys()) for program in installed.keys(): if installed[program]: print "You have %s (%s)" % (program, programs[program]) else: print "*** Program %s was not found on the system" % (program,)
Name of scriptfile: findprograms.py (exercise class: Python)
3.2 Find old and large files in a directory tree
Write a function that traverses a user-given directory tree and returns a list of all files that are larger than X Mb and that have not been accessed the last Y days, where X and Y are parameters to the function. Include an option in this function that moves the files to a subdirectory trash under /tmp (you need to create trash if it does not exist).
Hints: Use shutil.copy and os.remove to move the files (and not os.rename; it will not work for moving files across different filesystems). First build a list of all files to be removed. Thereafter, remove the files physically. The age of a file can be tested with os.path.getatime or the os.stat functions. Read about these functions in the Python Library Reference. You may also want to read about the time module.
To test the script, you can run a script fakefiletree.py that generates a directory tree (say) tmptree with files having arbitrary age (up to one year) and arbitrary size between 5 Kb and 10 Mb:
fakefiletree.py tmptree
If you find that fakefiletree.py generates too many large files, causing the disk to be filled up, modify the arguments in the maketree function call. Remember to remove tmptree when you have finished the testing.
Name of scriptfile: old_and_large.py (exercise class: Python)
3.3 Estimate the chance of an event in a dice game
What is the probability of getting at least one 6 when throwing two dice? This question can be analyzed theoretically by methods from probability theory (the result is 1/6 + 1/6 - (1/6)*(1/6) = 11/36). However, a much simpler and much more general alternative is to let a computer program 'throw' two dice a large number of times and count how many times a 6 shows up. Such type of computer experiments, involving uncertain events, is often called Monte Carlo simulation.
Create a script that in a loop from 1 to n draws two uniform random numbers between 1 and 6 and counts how many times p a 6 shows up. Write out the estimated probability p/float(n) together with the exact result 11/36. Run the script a few times with different n values (preferably read from the command line) and determine from the experiments how large n must be to get the first three decimals (0.306) of the probability correct.
Hint: Check out the random module to see how to draw random uniformly distributed integers in a specified interval.
Remark. Division of integers (p/n) yields in this case zero, since p is always smaller than n. Integer p divided by integer n implies in Python, and in most other languages, integer division, i.e., p/n is the largest integer that when multiplied by n becomes less than or equal to p. Converting at least one of the integers to float (p/float(n)) ensures floating-point division, which is what we need.
Name of scriptfile: dice2.py (exercise class: Python)
3.4 Determine if you win or loose a hazard game
Somebody suggests the following game. You pay 1 unit of money and are allowed to throw four dice. If the sum of the eyes on the dice is less than 9, you win 10 units of money, otherwise you loose your investment. Should you play this game?
Hint: Use the simulation method from Exercise 3.3.
Name of scriptfile: dice4.py (exercise class: Python)
Week 4: Sep 27 - Oct 1 (Regular Expressions)
4.1 Count words in a text
Write a script that reads a filename and a word from the command line, and reports the number of times the word occures in the file. When an optional argument -i is provided at the command line, the count should be case insensitive. Another command line flag -b should make the script respect word boundaries. Consider the following text in the file football.txt:
Football is a game involving two teams, 11 players on each team, three referees, two goals and a ball. Players use their feet to kick the ball into the opponent's goal. Goal keepers can use both feet and arms inside a certain area. After 90 minutes, the Germans win the game.
Running the script count_words.py on this file should report:
$ python count_words.py football.txt ball Number of occurances of string 'ball': 3 $ python count_words.py -i football.txt goal Number of occurances of string 'goal' (case insensitive): 3 $ python count_words-py -i -b football.txt goal Number of occurances of word 'goal' (case insensitive): 2 $ python count_words-py -b football.txt goal Number of occurances of word 'goal': 1
Name of scriptfile: count_words.py (exercise class: Regex)
4.2 Find errors in regular expressions
Consider the following script:
#!/usr/bin/env python """Find all numbers in a string.""" import re r = r"([+\-]?\d+\.?\d*|[+\-]?\.\d+|[+\-]?\d\.\d+[Ee][+\-]\d\d?)" c = re.compile(r) s = "an array: (1)=3.9836, (2)=4.3E-09, (3)=8766, (4)=.549" numbers = c.findall(s) # make dictionary a, where a[1]=3.9836 and so on: a = {} for i in range(0,len(numbers)-1,2): a[int(numbers[i])] = float(numbers[i+1]) sorted_keys = a.keys(); sorted_keys.sort() for index in sorted_keys: print "[%d]=%g" % (index,a[index])
Running this script produces the output
[-9]=3 [1]=3.9836 [2]=4.3 [8766]=4
while the desired output is
[1]=3.9836 [2]=4.3E-09 [3]=8766 [4]=0.549
Go through the script, make sure you understand all details, figure out how the various parts are matched by the regular expression, and find the error.
Name of scriptfile: regexerror.py (exercise class: Regex)
4.3 Explain the behavior of regular expressions
We want in a user interface to offer a compact syntax for loops: [0:12,4] means a loop from 0 up to and including 12 with steps of 4 (i.e., 0, 4, 8, 12). The comma and step is optional, so leaving them out as in [3.1:5] implies a unit step (3.1 and 4.1 are generated in this example). Consider the two suggestions for suitable regular expressions below. Both of them fail:
>>> loop1 = '[0:12]' # 0,1,2,3,4,5,6,7,8,9,10,11,12 >>> loop2 = '[0:12, 4]' # 0,4,8,12 >>> r1 = r'\[(.+):(.+?),?(.*)\]' >>> r2 = r'\[(.+):(.+),?(.*)\]' >>> import re >>> re.search(r1, loop1).groups() ('0', '1', '2') >>> re.search(r2, loop1).groups() ('0', '12', '') >>> re.search(r1, loop2).groups() ('0', '1', '2, 4') >>> re.search(r2, loop2).groups() ('0', '12, 4', '')
Explain in detail why the regular expressions fail. Use this insight to construct a regular expression that works.
Name of scriptfile: loop_regex.py (exercise class: Regex)
4.4 Interpret a regex code and find programming errors
The following code segment is related to extracting lower and upper limits of intervals (read Chapters 8.2.5 and 8.2.6):
real = \ r"\s*(?P<number>-?(\d+(\.\d*)?|\d*\.\d+)([eE][+\-]?\d+)?)\s*" c = re.compile(real) some_interval = "[3.58652e+05 , 6E+09]" groups = c.findall(some_interval) lower = float(groups[1][c.groupindex['number']]) upper = float(groups[2][c.groupindex['number']])
Execute the Python code and observe that it reports an error (index out of bounds in the upper = assignment). Try to understand what is going on in each statement, print out groups, and correct the code.
Name of scriptfile: findallerror.py (exercise class: Regex)
Week 5: Oct 11-15 (Regular expressions, Python tasks)
5.1 Generate data from a user-supplied formula
Suppose you want to generate files with (x,y) data in two columns, where y is given by some function f(x). (Such files can be manipulated by, e.g., the datatrans1.py script from Chapter 2.2.) You want the following interface to the generation script:
xygenerator.py start:stop,step func
x values are generated, starting with start and ending with stop, in increments of step. For each x value, you need to compute the textual expression in func, which is an arbitrary, valid Python expression for a function involving a single variable with name x, e.g., 'x**2.5*cosh(x)' or 'exp(-(x-2)**2)'. You can assume that from math import * is executed in the script.
Here is an example of generating 1001 data pairs (x,y), where x=0,0.5,1,1.5,...,500 and f(x)=x*sin(x):
xygenerator.py '0:500,0.5' 'x*sin(x)'
The xygenerator.py script should write to standard output - you can then easily direct the output to a file.
Try to write the xygenerator.py script as compactly as possible. You will probably be amazed about how much that can be accomplished in a 10+ line Python script! (Hint: use eval.)
Name of scriptfile: xygenerator.py (exercise class: Regex)
5.2 Write an improved function for joining strings
Perl's join function can join an arbitrary composition of strings and lists of strings. The purpose of this exercise is to write a similar function in Python (the string.join function, or the built-in join function in string objects, can only join strings in a list object). The function must handle an arbitrary number of arguments, where each argument can be a string, a list of strings, or a tuple of strings. The first argument should represent the delimiter. As an illustration, the function, here called join, should be able to handle the following example:
list1 = ['s1','s2','s3'] tuple1 = ('s4', 's5') ex1 = join(' ', 't1', 't2', list1, tuple1, 't3', 't4') ex2 = join(' # ', list1, 't0')
The resulting strings ex1 and ex2 should read
't1 t2 s1 s2 s3 s4 s5 t3 t4' 's1 # s2 # s3 # t0'
Hint: Variable number of arguments in functions is treated in Chapter 3.3.3, whereas Chapter 3.2.11 explains how to check the type of the arguments.
Name of scriptfile: join.py (exercise class: Python)
5.3 Use tools to document a script
Equip one of your previous scripts with doc strings. Use either HappyDoc or Epydoc and their light-weight markup languages to produce HTML documentation of the script. The documentation should be user-oriented in a traditional man page style, and both the documentation and the documented script should be handed in.
Name of scriptfile: your_script.py, your_doc.html (exercise class: Python)
5.4 Prefix name of digital image files with date and time
JPEG images taken by digital cameras normally have names like img_1238.jpg. For sorting purposes it might be convenient to have the time and date when the picture was taken as an initial part of the filename. Modern digital cameras encode a lot of information about the picture, including the time and date, into a header in the JPEG file. The coding scheme of the header often vary with the camera vendor, apparently making it necessary to use vendor-specific software to extract picture information. However, the jhead program can parse JPEG headers coming from most digital cameras.
Running jhead on a JPEG file results in output like
File name : tmp2.jpg File size : 179544 bytes File date : 2003:03:29 10:58:40 Camera make : Canon Camera model : Canon DIGITAL IXUS 300 Date/Time : 2002:05:19 18:10:03 Resolution : 1200 x 1600 Flash used : Yes Focal length : 11.4mm (35mm equivalent: 79mm) CCD width : 5.23mm Exposure time: 0.017 s (1/60) Aperture : f/4.0 Focus dist. : 1.17m Exposure bias:-0.33 Metering Mode: matrix Jpeg process : Baseline
A sample output is found here.
Write a Python function gettime that reads a text like the one above, extracts, the time and date when the picture was taken (Date/Time), and returns the time and date information as two tuples of strings (HH,MM,SS) and (YYYY,MM,DD). The first tuple corresponds to the time HH:MM:SS (hours, minutes, seconds), whereas the second tuple corresponds to the date YYYY:MM:DD (year, month, day). (Hint: It might be convenient to split each line wrt. : into a list l, re-join l[1:], split wrt. whitespace, and then wrt. :.)
Write another Python function prefix that takes the time and date string tuples from gettime as input, together with the name of the image file, and prefixes the filename with the date and time. For example, if img_4978.jpg is the original filename, and the tuples returned from gettime are (18,10,03) and (2002,05,19), the returned string from prefix reads
2002_05_19__18_10_03__img_4978.jpg
If the filename already is on this form, no prefix should be added (i.e., the original filename is returned).
In case you have collections of images produced by digital cameras, the filenaming functionality presented in this exercises can be very convenient. The JPEG header is destroyed by many photo manipulation and viewing programs, so keeping the date in the filename preserves this important information. Since the JPEG header is easily destroyed, you should apply jhead and the renaming procedure to fresh files not yet being processed by programs.
Name of scriptfile: jpegrename.py (exercise class: Python)
Week 6: Oct 18-22 (Class exercises, Python tasks)
6.1 Implement a class for vectors in 3D
The purpose of this exercise is to program with classes and special methods. Create a class Vec3D with support for the inner product, cross product, norm, addition, subtraction, etc. The following application script demonstrates the required functionality:
>>> from Vec3D import Vec3D >>> u = Vec3D(1, 0, 0) # (1,0,0) vector >>> v = Vec3D(0, 1, 0) >>> str(u) # pretty print '(1, 0, 0)' >>> repr(u) # u = eval(repr(u)) 'Vec3D(1, 0, 0)' >>> u.len() # Eucledian norm 1.0 >>> u[1] # subscripting 0.0 >>> v[2]=2.5 # subscripting w/assignment >>> print u**v # cross product (0, -2.5, 1) # (output applies __str__) >>> u+v # vector addition Vec3D(1, 1, 2.5) # (output applies __repr__) >>> u-v # vector subtraction Vec3D(1, -1, -2.5) >>> u*v # inner (scalar, dot) product 0.0
We remark that class Vec3D is just aimed at being an illustrating exercise. Serious computations with a class for 3D vectors should utilize either a NumPy array (see Chapter 4), or better, the Vector class in the Scientific.Geometry.Vector module, which is a part of ScientificPython (see Chapter 4.4.1).
Name of scriptfile: vec3d.py (exercise class: Class)
6.2 Extend the class from Exericse 6.1
Extend and modify the Vec3D class from Exericse 8.27 such that operators like + also work with scalars:
u = Vec3D(1, 0, 0) v = Vec3D(0, -0.2, 8) a = 1.2 u+v # vector addition a+v # scalar plus vector, yields (1.2, 1, 9.2) v+a # vector plus scalar, yields (1.2, 1, 9.2)
In the same way we should be able to do a-v, v-a, a*v, v*a, and v/a (a/v is not defined).
Name of scriptfile: vec3d_ext.py (exercise class: Class)
6.3 Vectorize a constant function
The function
def initial_condition(x): return 3.0
does not work properly when x is a NumPy array. In that case the function should return a NumPy array with the same shape as x and with all entries equal to 3.0. Perform the necessary modifications such that the function works for both scalar types and NumPy arrays.
Name of scriptfile: vectorize_function.py (exercise class: Python)
6.4 Vectorize a numerical integration rule
The integral of a function f(x) from x=a to x=b can be calculated numerically by the Trapezoidal rule:
Integral of f(x) from a to b = (h/2)*(f(a) + f(b)) + \ h*sum(i=1,...n-1) f(a+i*h)
where h equals (b-a)/(n-1). Implement this approximation in a Python function containing a straightforward loop.
The code will run slowly compared to a vectorized version. Make the vectorized version and introduce timings to measure the gain of vectorization. Use the functions
f_1(x) = 1+x f_2(x) = exp(-x*x)*log(x + x*sin(x))
as test functions for the integration. (Hint: Implement f such that it operates on a vector x of all the evaluation points a+i*h, i=0,... n-1.)
Name of scriptfile: vectorize_integration.py (exercise class: Python)
6.5 Automate the creation of runtime examples
Create a script that takes the name of another script, an output filename, and arguments needed to run the other script, and based on these inputs generates a file containing the source code of the script and a runtime example in a special comment section at the bottom of the output file. For instance, running the script on the following file (bar.py):
#!/usr/bin/env python def foo(arg1, arg2): return int(arg1) + int(arg2) if __name__ == "__main__": import sys print foo(sys.argv[1], sys.argv[2])
by invoking:
python automate_runtime.py bar.py assignment.txt 2 3
should result in the following output (in assignment.txt):
#!/usr/bin/env python def foo(arg1, arg2): return int(arg1) + int(arg2) if __name__ == "__main__": import sys print foo(sys.argv[1], sys.argv[2]) """ Run time example: python bar.py 2 3 5 """
Name of scriptfile: automate_runtime.py (exercise class: Python)
Week 7: Oct 25-29 (Class exercises, Python tasks)
7.1 Make a class for sparse vectors
The purpose of this exercise is to implement a sparse vector. That is, in a vector of length n, only a few of the elements are different from zero:
>>> a = SparseVec(4) >>> a[2] = 9.2 >>> a[0] = -1 >>> print a [0]=-1 [1]=0 [2]=9.2 [3]=0 >>> print a.nonzeros() {0: -1, 2: 9.2} >>> b = SparseVec(5) >>> b[1] = 1 >>> print b [0]=0 [1]=1 [2]=0 [3]=0 [4]=0 >>> print b.nonzeros() {1: 1} >>> c = a + b >>> print c [0]=-1 [1]=1 [2]=9.2 [3]=0 [4]=0 >>> print c.nonzeros() {0: -1, 1: 1, 2: 9.2} >>> for ai, i in a: # SparseVec iterator print 'a[%d]=%g ' % (i, ai), a[0]=-1 a[1]=0 a[2]=9.2 a[3]=0
Implement a class SparseVec with the illustrated functionality. Hint: Store the nonzero vector elements in a dictionary.
Name of scriptfile: SparseVec.py (exercise class: Class)
7.2 Assignment and in-place modifications of NumPy arrays
Consider the following script:
from scitools.numpytools import * x = sequence(0, 1, 0.5) # y = 2*x + 1: y = x; y*=2; y += 1 # z = 4*x - 4: z = x; z*=4; z -= 4 print x, y, z
Explain why x, y, and z have the same values. How can be script be changed such that y and z get the intended values?
Name of scriptfile: NumPy_assignment.py (exercise class: Python)
7.3 Implement Exercise 3.3 using NumPy arrays
Solve the same problem as in Exercise 3.3, but use NumPy and a vectorized algorithm. That is, generate two (long) random vectors of uniform integer numbers ranging from 1 to 6, find the entries that are 6 in one of the two arrays, count these entries and estimate the probability. Insert CPU-time measurements in the scripts and compare the plain Python loop and the random module with the vectorized version utilizing NumPy functionality.
Hint: You may use the following NumPy functions: random.randint, ==, +, >, and sum (read about them in the NumPy reference manual).
Name of scriptfile: dice2_NumPy.py (exercise class: Python)
7.4 Implement Exercise 3.4 using NumPy arrays
Solve the same problem as in Exercise 3.4, but use NumPy and a vectorized algorithm. Generate a random vector of 4*n uniform integer numbers ranging from 1 to 6, reshape this vector into an array with four rows and n columns, representing the outcome of n throws with four dice, sum the eyes and estimate the probability. Insert CPU-time measurements in the scripts and compare the plain Python solution in Exercise 3.4 with the version utilizing NumPy functionality.
Hint: You may use the NumPy functions random.randint, sum, and < (read about them in the NumPy reference manual, and notice especially that sum can sum the rows or the columns in a two-dimensional array).
Name of scriptfile: dice4_NumPy.py (exercise class: Python)
7.5 Process comma-separated numbers in a file
Suppose a spreadsheet program stores its table in a file row by row, but with comma-separated rows, as in this example:
"activity 1", 2376, 256, 87 "activity 2", 27, 89, 12 "activity 3", 199, 166.50, 0
Write a script that loads the text in the first column into a list of strings and the rest of the numbers into a two-dimensional NumPy array. Sum the elements in each row and write the result as
"activity 1" : 2719.0 "activity 2" : 128.0 "activity 3" : 365.5
The script should of course treat any number of rows and columns in the file. Try to write the script in a compact way.
Name of scriptfile: process_spreadsheet.py (exercise class: Python)
Week 8: Nov 1-5 (Class exercises, Python tasks)
8.1 Matrix-vector multiply with NumPy arrays
Define a matrix and a vector, e.g.,
A = array([[1, 2, 3], [4, 5, 7], [6, 8, 10]], float) b = array([-3, -2, -1], float)
Use the NumPy reference manual to find a function that computes the standard matrix-vector product A times b (i.e., the vector whose i-th component is sum from j=0 to 2 of A[i,j]*b[j]).
Name of scriptfile: matvec.py (exercise class: Python)
8.2 Replace lists by NumPy arrays
Modify the convert2.py script from Chapter 2.5 such that floating-point values are stored in NumPy arrays instead of plain Python lists.
Name of scriptfile: convert2_wNumPy.py (exercise class: Python)
8.3 Equip class Grid2D with subscripting
Extend the Grid2D class from Chapter 4.3.5 with functionality such that one can extract the coordinates of a grid point i,j by writing:
x, y = grid[i,j]
when grid is some Grid2D object. Also make sure that assignment, as in
grid[r,s] = (2, 2.5)
is an illegal option, i.e., we are not allowed to change the grid coordinates.
Name of scriptfile: Grid2D.py (exercise class: Class)
8.4 Extend the functionality of class Grid2D
Consider class Grid2D from Chapter 4.3.5. Extend this class with the following features:
- a __repr__ method for writing a string that can be used to recreate the grid object,
- a __eq__ method for efficiently testing whether two grids are equal,
- xmin, xmax, ymin, ymax read-only properties for extracting geometry information,
- replace the dx and dy attributes by read-only properties with the same names.
Organize the additional code such that you can say
from Grid2D_add import Grid2D
and get access to the extended Grid2D class, still under the name Grid2D. Hint: Use techniques from Chapter 8.6.13.
Also, you might want to consider the zen of the following code:
class Foo(object): def __init__(self, dx): self.dx = dx def bar(self, dx): print "dx is", self.dx class FooSub(Sub): def __init__(self, dx): # Do not call base class constructor, or else this will fail self._dx = dx def get_dx(self): return self._dx dx = property(get_dx, None, None)
Name of scriptfile: Grid2D_add.py (exercise class: Class)
8.5 Rock, Paper, Scissors
Description
Rock, paper, scissors, also know as roshambo, is a simple child's game that is frequently used to settle disputes. In the game, a rock breaks the scissors, the scissors cut the paper, and the paper covers the rock. Each option is equally likely to prevail over another. If the players choose the same object a draw is declared and the game is repeated until someone prevails. For more information than you ever thought it was possible to collect about rock, paper, scissors, check out the Web page of the World RPS Society. In this computerized version the human player competes against the computer which chooses a rock, paper, or scissors randomly. The game proceeds until the human player quits the game or until a predetermined score is reached (e.g., 11 pts.) at which time the final tally is displayed. Solutions with fewer numbers of if statements are considered more elegant.
Input
The human player enters the number of points required for a win. During the play of the game the human player selects whether to play a rock, paper, or scissors by using the keyboard. The human player may also end the game by pressing the Control-D sequence at any time. (Ending the game early does not allow a winner to be determined if the human player is ahead.)
Output
The program will display the winner of each roshambo round along with the running score. At the conclusion of the game, the computer will display the overall winner and the final score.
Sample session
Welcome to Rock, Paper, Scissors! How many points are required for a win? 3 Choose (R)ock, (P)aper, or (S)cissors? r Human: rock Computer: paper Computer wins! Score: Human 0 Computer 1 Choose (R)ock, (P)aper, or (S)cissors? r Human: rock Computer: scissors Human wins! Score: Human 1 Computer 1 Choose (R)ock, (P)aper, or (S)cissors? p Human: paper Computer: paper A draw Score: Human 1 Computer 1 Choose (R)ock, (P)aper, or (S)cissors? s Human: scissors Computer: paper Human wins! Score: Human 2 Computer 1 Choose (R)ock, (P)aper, or (S)cissors? r Human: rock Computer: scissors Human wins! Final Score: Human 3 Computer 1
This exercise is copied from openbookproject.net under the GNU Free Documentation License.
Name of scriptfile: roshambo.py
Week 9: Nov 8-12 (Python tasks)
9.1 Investigate the efficiency of various DAXPY implementations
A DAXPY operation performs the calculation u = a*x+y, where u, x, and y are vectors and a is a scalar. Implement the DAXPY operation in various ways:
- a plain Python loop over the vector indices,
- a NumPy vector expression u = a*x + y.
(The name DAXPY originates from the name of the subroutine in the standard BLAS library offering this computation.)
Name of scriptfile: daxpy.py
9.2 Investigate the efficiency of various DAXPY implementations cont.
This exercise is a continuation of exercise 9.1. This time, implement the following:
- a Fortran 77 subroutine with a do loop (called from Python).
The Fortran code for DAXPY can be found here.
Name of scriptfile: daxpy_fortran.py
9.3 Apply SWIG to an array class in C++
The purpose of this exercise is to wrap the MyArray from Chapter 10.2.3 such that MyArray objects can be used in Python in almost the same way as it is used in C++. Use SWIG to generate wrapper code. The code for MyArray can be found here.
Name of scriptfile: MyArray_wrap.py
9.4 Literary Analysis
Description
Your English teacher has just asked you to write a paper comparing two of the works from the free, online literature library at Project Gutenberg. Since you are a computer scientist, you decide to put your skills to use. You plan to compare your two favorite works of classic literature in terms of the vocabulary used in each. Since this a bit outside the scope of the assignment as described by your English teacher, you ask for permission before you proceed. Intruiged by your proposal, your English teacher agrees and you are ready to go.
You plan to write a program that will take a text file as input and return a report listing alphabetically all the words in the file and the number of occurances of each.
This exercise is copied from openbookproject.net under the GNU Free Documentation License.
Name of scriptfile: gutenberg.py
9.5 Math Quiz
Description
The following program runs a math quiz consisting of 10 multiplication problems involving operands between 1 and 10:
from random import randint correct = 0 for i in range(10): n1 = randint(1, 10) n2 = randint(1, 10) prod = n1 * n2 ans = input("What's %d times %d? " % (n1, n2)) if ans == prod: print "That's right -- well done.\n" correct = correct + 1 else: print "No, I'm afraid the answer is %d.\n" % prod print "\nI asked you 10 questions. You got %d of them right." % correct print "Well done!"
Your mission will be to do the following:
- Modify the program so that the user can choose how many questions they will be asked.
- Add levels to the program:
- Beginner - with operands between 1 and 10
- Intermediate - with operands between 1 and 25
- Advanced - with operands between 1 and 100
- Modify the message at the end so that it says:
Well done!
: if the user answered more than 2/3 of the questions correctly.You need more practice
: if they get between 1/3 and 2/3 of the questions correct.Please ask your math teacher for help!
: if they get less than 1/3 of the questions correct.
- Allow the user to start another quiz without restarting the program.
- Let the user choose the question type: addition, subtraction, multiplication, or mixed.
This exercise is copied from openbookproject.net under the GNU Free Documentation License.
Name of scriptfile: math_quiz.py
9.6 Data Types and Variables
Directions:
Use the python shell to help you answer these questions:
-
- What is the difference between a string and an integer/float?
- What makes a float different from an integer?
- Given a variable, x, what is the command to get python to print out the type of x?
- What is a keyword?
- What is a statement? Give 2 examples.
- What is an expression? Give 2 examples.
- What is the difference between a statement and an expression?
- The following statement produces no output when not run in the shell.
3.14 * 6 * 6
Modify it to produce output. - What is an operator?
- What problem arises in integer devision?
- I want to divide 1 by 3 and get a result like: 0.333333333333. What is the exact command to do this?
- HINT: you must use floats! What do floats have that integers do not have?
- Integer division always rounds which way? (up or down)
- What is concatenation, and on what type of variables (integers/floats/strings) does it operate on?
- Why do we use comments? (what is their purpose)
- Enter the following code:
>>> 1 == 1 >>> "1" == "1" >>> 1 == "1"
Why is the third line false, while the first 2 lines are true?
This exercise is copied from openbookproject.net under the GNU Free Documentation License.
Name of scriptfile: variables.py