Functional solution.  Could use a bit more refatoring.