# FizzBuzz in One Line

2013-02-03

Over the past month, I've relocated to San Francisco and started as part of the spring cohort at DevBootcamp. As a result, I have had less time to add new posts here.

Among the many highlights of last week at DBC, I learned a one-line implementation of FizzBuzz in Ruby. It's a clever piece of code and worth taking apart.

First, to review, the requirements of the classic FizzBuzz program are as follows: print out the numbers one to one hundred. If a number is divisible by three, print out "Fizz" instead of the number. Likewise, if a number is divisible by five, print out "Buzz." Finally, if a number is divisible by both three and five, print out "FizzBuzz."

Here's how to do all that using just one line in Ruby.

``````puts (1..100).map { |i| (fb = [["Fizz"][i % 3], ["Buzz"][i % 5]].compact.join).empty? ? i : fb }
``````

Naturally, the code above is far from transparent. Let's take it apart piece by piece.

We start by calling `puts` on an array, which will be the return value of the `map` function. The nice thing about `puts` is that it will iterate over an array, printing an element and then a new line each time.

Next comes the hairy part. We call `map` on one through one hundred. For each number, we assign a particular value to the `fb` local variable. Understanding that particular value is at the heart of this one-liner.

Let's start by assuming that we've passed three into the block, represented by `i`. The expression `i % 3` becomes `3 % 3` which evaulates to zero. Therefore, we'll have `["Fizz"]`. The zeroeth index of a one member array is the first member, and so the result will be `"Fizz"`. Second, the expression `i % 5` will become `3 % 5` which will evaluate to `3`. And this is the most important trick. In Ruby, when we ask for an index on an array which is larger than the array, e.g., `["a", "b", "c"]`, we won't get an error. Instead, we'll simply get `nil`. As a result, the expression `["Buzz"][3 % 5]` will become `["Buzz"]` which will finally become simply `nil`.

So, when `i` is three, the resulting array will be:

``````# step one
[["Fizz"][3 % 3], ["Buzz"][3 % 5]]
# step two
[["Fizz"], ["Buzz"]]
# step three
["Fizz", nil]
``````

In other words, every time we have a number which is evenly divisible by three, i.e., `i % 3 == 0`, we'll get a `"Fizz"` in our array. And every time we get a number which is evenly divisible by five, i.e., `i % 5 == 0`, we'll get a `"Buzz"`. If both conditions are satisfied, e.g., as with `15`, we'll get an array with both `"Fizz"` and `"Buzz"`, e.g., `["Fizz", "Buzz"]`.

With that down, we simply call `compact` on the resulting array, removing any `nil` members, and join the two members together into a string. If we have a `"Fizz"` and a `nil`, the `join` method is smart enough to drop the `nil`, and just leave `"Fizz"`. A `"Fizz"` and a `"Buzz"` will become `"FizzBuzz`. If we have two `nil` members, `join` will return an empty string.

We then assign the result of `compact` and `join` to a variable local to the block, i.e., `fb`.

The rest of the line is simply a ternary expression. If our `fb` string is an empty string, we return `i`, otherwise we return whatever has been assigned to `fb`.

And that is the FizzBuzz problem in one line. Just please don't write code like this in production.