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
Yesterday I attended a talk about truth tables. It was based on the premise of an interview question and whether the candidates were able to model and represent in code the appropriate truth table. The problem question was along the lines of "write a method that receives the month and the year and outputs how many days there are in that month".
Sounds easy, doesn't it? We all know which months have 30 and which 31 days in them. Apart from February, that is. February usually has 28 days, except that in leap years it has 29. How do we know which years are leap years? There are certain rules that allow us to determine leap years:
To sum it up, a year is a leap year when
The speaker used PHP code for a working solution, using multiconditional statements . Now we could use the same approach in Ruby with a multibranch conditional or maybe a Case statement and that would work just as well. But, this being Ruby, there's always another way. We can leverage two powerful Ruby features to model our truth table as a Hash:
Knowing all this, we can write our method as follows: def month_days(year, month) h = { %w(jan mar may jul aug oct dec) => 31, %w(apr jun sep nov) => 30, %w(feb) => ((year % 4 == 0) && (year % 400 == 0))  ((year % 4 == 0) && (year % 100 != 0)) ? 29 : 28 } h.select {k,v k.include? month}.values end $> puts month_days 1900, 'feb' 28 $> puts month_days 2000, 'feb' 29 $> puts month_days 1900, 'sep' 30 We use Arrays for the Hash keys and we use the ternary operator as a value for the february key. Our returning object then, is the value of a Hash key that is generated by filtering the original Hash's keys (Arrays) based on the desired month. Beautiful. Maybe it's just me getting more finicky in my old age or it's because I just spent a few hours reading though some horrible JavaScript code, but this looks and feels more readable and a bit more 'jenesaisquoi' than a big If or Case statement. Of course, Ruby being Ruby, there'll be a better way, so if you know of any feel free to share it with me by commenting below. 
