version 3; refactored; all tests pass