Ruby Tuesday – Functional fizzbuzz

Today we are going to take a quick break from looking at some different library methods for today’s Ruby Tuesday post.

Last Friday I was going back and forth with a teammate over our chat tool about some different programming problems we could use to do some very basic screening of candidates, and I mentioned that if nothing else there is always fizzbuzz.

fizzbuzz, for anybody who at this point has yet to encounter it, even by just blog posts such as this, take a number N, and prints out fizz if the number is a multiple of three, buzz if the number is a multiple of 5, fizzbuzz if the number is both a multiple of three and five, or else just the number itself if none of the conditions hold true.

While fizzbuzz, isn’t a great problem, and, depending on the circles you are in, can be pretty worthless because most candidates have seen it already, it can still have its place. But, sadly, there are developer candidates we encounter that have a hard time translating the problem above, which states the algorithm in English, directly into code. The reason I think fizzbuzz can be interesting, as I mentioned to my coworker, is it can give candidates a chance to show off some more advanced topics that they wish to show off, if they wish.

After mentioning that benefit to him on Friday, I came across the post “Bro, Do You Even FizzBuzz?!?” on fizzbuzz in Clojure and shows off a solution of not using the modulus operator to determine the result.

I decided I would attempt to translate the solution to Ruby, to prove out the point of our conversation.

def do_fizzbuzz(n)
fizz = ['', '', 'fizz'].cycle.lazy
buzz = ['', '', '', '', 'buzz'].cycle.lazy
fizzbuzz = fizz.zip(buzz).map(&:join)
puts (1..n).
zip(fizzbuzz).
map {|number, translation| if translation.empty? then number else translation end}.
join("n")
end

First, we declare the “fizzes” as a lazy repeating array of blank strings, where every third is the string ‘fizz’, by using cycle and lazy. We do the same for the occurrences of buzz, but have it be every fifth item in an array.

We then zip the fizz and buzz lazy enumerations together, and then map over that result joining the two strings together, e.g. ["", ""].join, ["fizz", ""].join, ["", "buzz"].join, or ["fizz", "buzz"].join.

After we have our lazy enumeration of fizzbuzz translations, we take the range of numbers from 1 to N, zip that together with the translations, pick the translation if it is not an empty string, otherwise pick the number, and then join all of the results together with a newline separator, so each entry will print on its own line.

There you have it, a functional programming style fizzbuzz solution that does not use the modulus operator to arrive at a solution.

–Proctor