Code looks done. It passes all the test cases, and I added a few more to detect input errors. The code is a little redundant, and I might try to make it more concise, but for now I think it looks cool.