15 Exercises to Know A Programming Language: Part 1
There's a popular post on Digg right now entitled "15 Exercises for Learning a New Programming Language." The list is discouragingly non-structural: calculate a function and print out one thing if it's \<= , another if it's greater, get system time and format it, etc. The exercises, while fine enough for familiarizing yourself with string formatting, don't really provide a sense of a programming language.
If you applied for a job, or even an internship, using language x, you would embarrass yourself if you did not know considerably more than what's covered in Prashant Mhatre's list. My exercises are harder, but require no more than the minimal level of competence required to claim that one "knows" a programming language.
If you're a more seasoned developer, these exercises will highlight the more salient differences between languages. The hope is that, rather than just getting "the answer," these exercises are hard enough to engage you but simple enough so as to be a place to explore the new language's idioms. If, as I believe, there's no such thing as a universally "better programming language" but only languages that better fit our own personalities and experiences, these exercises should be hard enough to require problem-solving in the new language, but straightforward enough that the problems are language and library related, not algorithmic.
The series has 3 parts: calculations, data structures, and libraries.
At the end of the first series, you will have implemented a non-trivial CPU-intensive application with a GUI front-end. You will have a good sense of the language's expressiveness for calculations and have seen some corner cases: underflow, stack overflow (probably), GUI behavior during a CPU-intense calc. You'll undoubtedly have made some mistakes and dealt with the debugging experience. Hopefully, you'll have separated model and view and have some idea of how a larger project would be organized. Hopefully, you'll have turned to unit-testing to ratchet your progress and will have a sense of the iterative "feel" of the language and environment.
Write a program that takes as its first argument one of the words 'sum,' 'product,' 'mean,' or 'sqrt' and for further arguments a series of numbers. The program applies the appropriate function to the series.
Educational goals of exercise 1:
Requires basic control flow, basic operators, and the math library. (Complex numbers available?)
What are arrays like?
What about parsing / implicit conversion?
Are functions first-class (availability of Map() and Apply())?
Error handling: What happens on invalid data?
Write a program that calculates a Haar wavelet on an array of numbers. The Haar transform works as follows: calculate the average and difference-from-the-average of pairs of input values. Gather averages as the first part of the returned array, "detail coefficients" as the second. Recurse until the first value is the average is the entire series (steps required = log base 2(array length)).
For instance, Haar([8, 5]) -> [6.5, 1.5]
6.5 = (8+5)/2
1.5 = 8 - (8+5)/2)
Haar([8, 5, 7, 3) -> [5.75, 1.75, 0.75, -0.25]
Step 1 -> [6.5, 5, 1.5, 2]
1st and 3rd values as prior example, 2nd and 4th transform applied to 7 and 3
Step 2 -> Recurse, using [6.5, 5] and [1.5, 2] as bases. (N.B.: Average([8,5,7,3]) == 5.75)
Educational goals of exercise 2:
How are functions declared and organized?
What about recursion? What happens when I pipe in a megabyte of data? (Is tail-recursion available?)
How does the environment support unit-testing?
Exception handling: what if the array has an odd-numbered length?
Data representation -- what about rounding errors on very small coefficients?
Write a program that takes as its arguments a the name of a bitmapped image (Start with images from the Waterloo Repertoire Grayset 2: http://links.uwaterloo.ca/greyset2.base.html) . Apply the Haar wavelet to the pixel values. Save the results to a file.
Educational goals of exercise 3:
File manipulation and binary I/O.
Standard (?) library.
Type-strictness (what's involved in treating a pixel value as a number?)
Emerging sense of program structure / refactoring.
Using the outputs of the previous exercise file, write a GUI program that reconstitutes the original bitmap (N.B.: The Haar wavelet is lossless).
Educational goals of exercise 4:
GUI behavior, including events, file manipulation, and behavior with long-running calculation (async calcs?).
Write a GUI program that can:
i. Open bitmapped images in a variety of formats,
ii. Apply the Haar partially (e.g., a "Do a step" button that applies the Haar transform but does not recurse).
iii. Visualize a partial Haar transform (i.e., scale the detail coefficients into the range 0-255 and display them as pixel values)
iv. Clip to 0 coefficients whose absolute values are \< x. (N.B.: This is a lossy-y transform that allows for great compression)
v. Reconstitute a bitmap from values created by the above transform.
vi. Displays the time it takes a bitmap to be transformed, clipped, and reconstituted.
Mental exercises: What could be reused if I wanted to do these exercises with sound? How would a plug-in model for wavelet functions work? How would a purely dynamic wavelet function (i.e., fill a textfield with code) work?
Educational goals of exercise 5:
Non-trivial program structure.
Component model, dynamism.
Environment: debugging, iterative development, testing, version control, refactoring, etc.
These exercises favor functional languages and those with list-processing capabilities. Lisp, Ruby, and Smalltalk programmers would breeze through the coding aspects of these exercises easily, although the GUI exercises might reveal performance issues. Those using imperative non-managed languages (C and C++, possibly Pascal) may find the lack of a standard GUI library troublesome. However, their performance on the bitmap manipulation tasks ought to be high. Those using managed languages such as Java, C#, and VB.NET will find the GUI portions easy, but may find that their program development isn't as smoothly iterative as development in the more dynamic languages have. Such programmers may also see "spikes" in their performance as automatic memory management kicks in.