When anyone mentions a coding exercise they had to do for an interview or a class, I have a habit of getting it stuck in my mind and having to go home and work it out myself.
One of my co-workers, a reporter, has recently started to teach himself Ruby. He took a Java class in college and always had a kind of hankering to get back into programming, so when he and his girlfriend had a fight about chores, he decided to make a web app to help them figure out who was doing what, and to keep track of compliance and send email reminders. Everyone who’s looking for the motivation to re-learn programming needs some precipitating excuse, and that’s his, apparently. Certainly as good a reason as any. He’s been going through a Ruby book meant for the absolute beginner to programming, “Learn to Program,” by Chris Pine.
My basic realization for the central algorithm was that all you need to know to add up Roman numerals (in their standardized modern variety anyway) is that the value of each letter is added to the total, unless it’s worth less than the one after it, in which case it gets subtracted from the total. That’s the simplest way to compute it, anyway.
Alternatively, you could go through the two-step process of identifying one- and two-letter sequences (like ‘X’ and ‘IV’) and then adding them. One could argue that that’s easier to read because the one- and two-letter sequences map very well conceptually to the Arabic notation that we think in.
Which would be an interesting question to ask an expert, but in the meantime, here are two solutions that are as concise as I could make them without getting into obnoxious trickiness for its own sake. The first one uses a classic ‘for’ loop, and the second one uses the more elegant functional programming methods map and reduce from the ECMAScript 5 spec, which you unfortunately can’t count on being available in every browser, but are pretty awesome:
The For Loop Version
The Functional Programming Version
Explaining map and reduce is beyond the scope of this blog post (try here instead), but just notice that there are no local variables in the second version, except the number map itself, and the function arguments. I find that easier to read, personally. Fewer things to keep track of in my head.
Then check out the Ruby version:
Looks a little repetitive in the middle there. I bet it’s possible to write something a bit more succinct — Ruby people are always saying that you could write a fully-featured word-processing program in seven lines. I guess I’ll find out when I learn the language myself.