FizzBuzz is a simple kids game, often used as a test at programming interviews. It goes like this:
"Write a program that prints the numbers from 1 to 100. But for multiples of three print “Fizz” instead of the number and for the multiples of five print “Buzz”. For numbers which are multiples of both three and five print “FizzBuzz”." Once you've realised that there's a unique outcome for each permutation of the two conditions, the solution is pretty obvious. Let's have a look at the truth table: (n % 3 == 0)  (n % 5 == 0)  outcome  true false 'Fizz' false true 'Buzz' true true ' FizzBuzz' false false number We can express this as a pretty standard multiconditional statement: (1..100).each do n if (n % 3 == 0) && (n % 5 != 0) puts 'Fizz' elsif (n % 3 != 0) && (n % 5 == 0) puts 'Buzz' elsif (n % 3 == 0) && (n % 5 == 0) puts 'FizzBuzz' else puts n end end This will work fine, however I think we can do better than that. Now, remember we already saw how we can use a Hash to represent a truth table? Well, this is a truth table right here so there's nothing stopping us from using a Hash. Our clue is that the outcome of our table is a unique value (Fizz, Buzz, FizzBuzz or the given number), so this will be the key of our hash. We can now write a method like this one: def fizz_buzz(n) h = { 'Fizz' => (n % 3 == 0) && (n % 5 != 0), 'Buzz' => (n % 3 != 0) && (n % 5 == 0), 'FizzBuzz' => (n % 3 == 0) && (n % 5 == 0) } h.key(true)  n end First, we define a Hash whose values will evaluate to true or false depending on the number we pass into it. Now here's the sweetness: since the conditions that are evaluated to produce each value are mutually exclusive, only a maximum of one of our Hash keys will have the value of 'true' for any given number. We then make sure we return this 'true' key (h.key(true)) from our method. Of course if all our keys have the 'false' value (i.e. the passed number is neither divisible by 3, nor by 5) then h.key(true) will evaluate to nil, so we use the logical OR operator to ensure that in this case we return the actual passed number. Let's try it out: $> puts fizz_buzz(2) => 2 $> puts fizz_buzz(3) => Fizz $> puts fizz_buzz(5) => Buzz $> puts fizz_buzz(7) => 7 $> puts fizz_buzz(15) => FizzBuzz Sweet! Now, to solve the original problem all we have to do is $> (1..100).each {num puts fizz_buzz(num)} Hashtables in any language are a powerful construct. Hashes in Ruby though are truly awesome! They provide unrivalled versatility and expressiveness, just like most things Ruby. Use them, enjoy them, you won't find anything like them anywhere else! :)
3 Comments
asdfgh
4/30/2015 03:43:26 pm
h.key(true) ? h.key(true) : n  ? is "if".
Reply
Fred
4/30/2015 03:58:50 pm
Good point! Easily solved though by changing the ternary to h.key(true)  n
Reply
5/1/2015 01:44:03 am
I'm a CleanCode maniac and love the noifsapproach tho ... it's almost 5x slower in this case ;)
Reply
Leave a Reply. 
