CodeKata – Binary search (chop) in Ruby
Wednesday, February 24th, 2010On Monday I was home with manflu and, facing a terrible lack of sympathy from a considerably pregnant wife, decided to start learning Ruby. I finished the Ruby Koans, a set of failing tests that walks you through aspects of the language. I now think that, after ‘Hello, World!’ and some basic algebra, TDD would be the best way to teach and learn programming in general.
Last night I found my way to CodeKata and started at Kata 2 for instant gratification. Kata 2 is to implement a binary search algorithm. My first try was just a linear search, which passed the tests, but wasn’t a binary search and for very big sets of test data is impractical. My second try is a recursive binary search:
def chop(needle, haystack)
# Special cases
return -1 if haystack.length == 0
if haystack.length == 1
return 0 if haystack[0] == needle
return -1
end
# find the middle element
mid = (haystack.length / 2).round
return mid if haystack[mid] == needle
if haystack[mid] > needle
#needle is in first half
return chop(needle, haystack[0..(mid-1)])
else
#needle is in second half
result = chop(needle, haystack[mid..haystack.length])
return result == -1 ? -1 : result + mid
end
end
My third try converts the recursive algo into an interative one:
def chop(needle, haystack)
depth = 0
while true
# Special cases
return -1 if haystack.length == 0
if haystack.length == 1
return depth if haystack[0] == needle
return -1
end
# find mid point
mid = (haystack.length / 2).round
return mid + depth if haystack[mid] == needle
# trim haystack based on which end to follow
if haystack[mid] > needle
#needle is in first half
haystack = haystack[0..(mid - 1)]
else
haystack = haystack[mid..haystack.length]
depth += mid
end
end
end
I found that while I was writing the different implementations I had a lot of love for these little chips of Ruby. Maybe it was the very expressive syntax (such as the Yoda-esque return X if condition) or just the nature of TDD itself. Either way I’m really enjoying Ruby.

