Posts Tagged ‘learn’

Programming Praxis – Learn A New Language

June 25, 2010

The goal in today’s Programming Praxis exercise is to solve a previous exercise in a language you’re not proficient in. Since I’m a big fan of statically typed languages, I figured I’d try a dynamically typed one today, the two most obvious options being Python and Ruby. I’ve done a little Python coding (among others, it’s the scripting language for the text editor I use). Of the two, Ruby has always seemed the more interesting one (partly because it embraces functional programming more than Python does), but I haven’t yet had occasion to use it. Let’s remedy that.

As for the exercise, I picked Steve Yegge’s Phone-Screen Coding Exercises, figuring seven different small problems might cover slightly more ground than one bigger one.

Reversing a string works just like in Haskell, save for the fact that we have to explicitly convert the string to a character array.

def reverse(s)
    s.chars.inject {|rev, x| x + rev }

For calculating Fibonacci numbers we can’t use the typical Haskell solution of zipping an infinite sequence with itself, so instead we just use a fold, keeping a buffer of the last two values calculated.

def fib(n)
    (2..n).inject([0,1]) {|fs, i| [fs[1], fs[0] + fs[1]]} [[1, n].min]

For the 12 times table, the solution is basically the same as the Haskell one, though since Ruby has no list comprehensions we have to use a nested map.

def timestable
    (1..12).map {|r| puts (1..12).map {|c| "%4d" % (r * c)}.join}

Summing numbers from a file is straightforward: read the lines of the file, convert them to numbers and sum them up, same as in Haskell.

def sum_from_file(file) {|f|}

Printing the odd numbers from 1 to 99 is trivial as well.

def odd_numbers
    p (1..99).find_all(&:odd?)

Getting the highest integer in a list can be done with a simple fold.

def maximum(array)
    array.inject {|max, i| i > max ? i : max}

Again, identical to the Haskell version, if a bit longer due to the lack of partial application.

def to_rgb(r, g, b)
    sprintf("%02x%02x%02x", r, g, b)

As usual, our tests:

puts reverse("Hello, World!")
p (0..10).map {|x| fib x}
puts sum_from_file("numbers.txt")
puts maximum([-1,3,2])
puts to_rgb(255, 128, 65)

Naturally, a test this short is hardly conclusive evidence, but so far Ruby doesn’t disappoint. All seven functions are one-liners, as you would expect from any competent language, though this is slightly marred by the need for end keywords. I prefer the Haskell and Python approach in this, since it eliminates these useless almost-empty lines. On the plus side, first-class functions and all the common enumerable methods mean you can often directly transcribe the Haskell solution, which is nice. It won’t be replacing Haskell as my favorite language any time soon, but out of the more mainstream languages you could do a lot worse than Ruby.