A question came up today about how to reverse a sentence. Word by word, preserving periods etc. I’ve done stuff like this before but I really saw an opportunity to solve this contrived quiz type question with TDD. It’s perfect really. Tedious string checking? Screw it. Let my test tell me when I’m done.
Ok so I could have probably done this more comfortably in Java but it would have been more lines. I banged this out in Ruby, including “learning” test cases (it’s really easy) in about an hour. At one point I realized how easy string manipulation is in Ruby for this and I literally said, “holy shit Ruby is amazing”. And then the edge cases started happening. I was only handling periods and my algorithm fell over flat on three sentences because I was trying to do a string[start, end] when it’s really string[start, length]. I fixed it with learning the String#slice syntax.
Ok enough fanboi service. There’s two files. One’s the test and one’s the class. Run the test and not the class (ie: ruby tc_reverser.rb).
tc_reverser.rb:
I have to apologize for the scrollbars in the above posted code. I tried many different ways of escaping carriage returns for better formatting but it would have required a lot of changes to deal with the \n and so on in the tests. I had something nicely formatted working but the tabs and spaces for alignment then screwed the test and broke the pretty formatting a different way.
reverser.rb:
When you run the test case it looks like this:
Loaded suite ~/src/ruby/tc_reverser
Started
Set television first our. Today up it picked just dad. Television a have you do? Them of two have we, know you, yeah, well. Wow! Rich be must you. You teasing he's, honey, oh. Sets television two has nobody.
TEST_EVERYTHING OK!
.
Man, up shape. Slacker a you're. Life your of rest the for slacker a be to want you do?
TEST_MULTIPLE_SENTENCE_DELIMITERS OK!
.
1985 in States United the of president who's, huh, boy future, me tell then?
TEST_QUESTION_COMMA OK!
.
Bastard space you. Pine my killed you.
TEST_REVERSER OK!
.
Finished in 0.003567 seconds.
`
4 tests, 4 assertions, 0 failures, 0 errors
`
Marty McFly would be proud. So, some limitations. First, I don’t handle elipsis (…) characters at all. It splits on sentence delimiters which one is a period. The eplisis would cause major weirdness. I also don’t handle recapitalizing the word “Dad” as you can see in the “test_everything” test. This would require language parsing or a massive pick list. I also don’t handle slang or abbreviations. For example, “You told ‘em?” would turn into “‘em told you?” which might not be exactly right.
There are many other edge cases that this thing would fall flat on. My test case tests what functionality I wanted and nothing more.
Ruby’s String#slice was super handy on this as well as capitalize, reverse and even a regex split that I didn’t use (amazing!). You can see it here. It would split text into an array really easily:
But then I’d lose the delimiter character (!?. etc) and would have to save it, search it or some other nonsense. Still, really neat that you can split on a regex.