[SUMMARY] FizzBuzz (#126)

R

Ruby Quiz

The discussion around this quiz touched on what the interviewer is actually
looking for when they ask this question. Most people seem to agree that at
least one goal is to establish that you are capable of writing some code.

The other item we assume the interviewers are searching for is some degree of
cleverness. The interesting thing is that we don't seem to agree on the amount
of cleverness. Some feel you should provide a no-nonsense solution, solving the
problem just as you would if it was a small part of your work for the day.
Others feel it's better to let your style flare a bit and show off unusual
approaches to solving the problem. The solutions covered both approaches very
well.

I'll start with my own, just because I can explain my thinking behind it.
Here's the code:

#!/usr/bin/env ruby -w

1.upto(100) do |i|
if i % 5 == 0 and i % 3 == 0
puts "FizzBuzz"
elsif i % 5 == 0
puts "Buzz"
elsif i % 3 == 0
puts "Fizz"
else
puts i
end
end

The interesting part of this solution is what happened in my head. When I began
to code it up and realized the combined test would need to come first, I
experienced a brief moment of doubt in my logic and considered writing some
tests. After a calming breath, I convinced myself that this problem was easy
enough to not worry about them. I was confident I was right, though this
problem is about the upper limit of what I am comfortable doing without tests
and I might have caved-in easier under the pressure of a real interview. For a
nice test-driven solution do look over Jason Merrill's response to the quiz.

There's nothing tricky in my code, of course. I walk the numbers and perform
divisibility tests to decide what to print. Many solutions took a very similar
approach with minor variations. One such variation was to change the first
divisibility check to:

if n % 15 == 0 # darrin kirby's code

# ... or ...

when num.dividable_by?(3*5): "fizzbuzz" # Rene Koning's code

My opinion was that the two test approach was a more self-documenting way to
code it up, but I found Rene's solution to be a good balance.

Looking back on my code now that I've examined over 70 solutions, I'm painfully
aware of how much duplication there is in it. I repeat the divisibility tests
and the calls to puts() in almost every branch. A lot of solutions DRYed that
code up. Two common ways to do it were to pre-calculate the divisibility tests
and to move puts() outside of the if/case statements. Here's some code from
Bill Guindon that shows off both tricks:

(1..100).each do |x|
m3 = x.modulo(3) == 0
m5 = x.modulo(5) == 0

puts case
when (m3 and m5) then 'FizzBuzz'
when m3 then 'Fizz'
when m5 then 'Buzz'
else x
end
end

You can see we're down to a single call to puts() here and The results of the
tests are cached for convenient reuse. I think that's an improvement.

We do still have duplication here too though, on a smaller scale. First, the
test results are still checked multiple times. That's not as bad as redoing the
whole test, but it would be nice if it wasn't needed. More importantly, the
'Fizz' and 'Buzz' Strings are repeated in the 'FizzBuzz' String. Obviously,
there is still room for DRYing things up.

Daniel Martin sent in a good example of code that only does each step once:

(1..100).each{|i|
x = ''
x += 'Fizz' if i%3==0
x += 'Buzz' if i%5==0
puts(x.empty? ? i : x);
}

Here the output is built up piece by piece. A divisible by three check adds the
'Fizz' and divisible by five the 'Buzz' If the number happens to be divisible
by both they will be combined to yield 'FizzBuzz' From there, a quick check is
needed to see if the String is still empty?(), meaning that we should output the
digit instead.

It's short code, easy to follow, and it doesn't give me any doubts about it's
functionality. I think it's a solid approach to take.

Of course, if you're a fan of clever, don't miss MenTaLguY's lambda calculus
solution.

My thanks to everyone who blew the quiz record out of the water time around!
I'll be looking for more boring problems now just because staying on top of the
submissions was a real challenge. ;)

Tomorrow we will show just how versatile Ruby programmers can be and weave a few
blankets...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top