http://courses.cs.washington.edu/courses/cse341/13sp