# Perl One Liner: FizzBuzz

#### Abstract

## What's FizzBuzz?

I must confess that I ignore who invented the FizzBuzz problem but it is a nice, and simple, first interview question. It has both the intent of make the candidate relax and understanding if he/she is able to write a very simple program... and you cannot immagine how many people are not able to code this simple program.

The text of the exercise is more or less the following one: "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»". It could be possible that I inverted Fiiz and Buzz... but the exercise is the same.

## Our Implementation(s)

Anyway, we are not interested in providing a vanilla implementation for the FizzBuzz problem. We are looking for a Perl one-liner version. This means that the implementation will just consist of one or more simple instructions directly on the terminal command line using `perl -e '...'`.

Let's proceed with the first version (output is truncated):

nids@crimson: ~/Test/FizzBuzz$ perl -le 'for(1..100){$x=!($_%5);$y=!($_%3);$_=($y?"Fizz":"").($x?"Buzz":"")if($x+$y);print}' 1 2 Buzz 4 Fizz Buzz 7 8 Buzz Fizz 11 Buzz 13 14 FizzBuzz 16 . . . . . 97 98 Fizz Buzz nids@crimson: ~/Test/FizzBuzz$

It works. Let's explain why.

For each natural number in the range [1,100], `$x` will take the value `true` if the number is a multiple of 5 and `$y` will do the same if the number is a multiple of 3. This is done in the following way: if a number is divisible my another, the result of the modulo operation `%` is 0. 0 is equivalent to `false`, we negate it and we get `true`. More intesting are the other possible values of modulo: any possible other output of modulo is just another number and the logical negation of any possible number, different from 0, is 0.

We then use the `if` statement as a modifier. In Perl, the constuct `STATEMENT if COND;` is equivalent to `if COND { STATEMENT; }` and we just save some parenthesis.

We put the result of the construction of the output (if divisible by 3, 5 or both) in the automatic variable `$_` that will be printed by default just calling `print` without any argument. If the number is not divisible by 3, 5 or both, we just leave it in `$_`, without touching it.

The condition of the `if` is an old C-programmer trick: booleans are just integers that can have value 0 or 1. We can then replace the `||` (or in Perl) with just one character: `+`.

Now, let's make it cooler.

Let's proceed with the second version (output is truncated):

nids@crimson: ~/Test/FizzBuzz$ perl -E 'say"Fizz"x!($_%5)."Buzz"x!($_%3)."$_"x(!!($_%5)&!!($_%3))for(1..100)' 1 2 Buzz 4 Fizz Buzz 7 8 Buzz Fizz 11 Buzz 13 14 FizzBuzz 16 . . . . . 97 98 Fizz Buzz nids@crimson: ~/Test/FizzBuzz$

First thing, we reverse the `for` statement and we make that postfix as we already did with the `if` in the previous case. The only problem with this is that the code executed as the body of the `for` must be a single statement.

First of all, we shorten the `print` using `say` instead. `say` acts exactly as `print` but it automatically adds a `\n` at the end of the printed string (`say` is available starting from Perl 5.10).

And now, the magic trick: we get rid of all the `if`s.

Let's think about the logic of the application. There are 4 separate cases: if the number is a multiple of 3; it the number is a multiple of 5; if a number is both a multiple of 3 and 5; and all the other numbers.

The case in which a number is both a multiple of 3 and 5 is just a special case of the first two ones. From a certain point of view, we could write something like (pseudocode):

if number mod 5 == 0 then write "Fizz" endif if number mod 3 == 0 then write "Buzz" endifIf the number is just a multiple of 5, the execution flow enters only the first statement but not the second. Similarly, a multiple of 3, we executes only the second one but for the numbers that are both multiples of 5 and 3 we execute both and we print "FizzBuzz".

How can we leverage this in Perl, in one statement without using `if`s?

Perl has a special operator called `x` which works in the following way: given a string `s` on the left hand side of the operator and a number `n` on the right hand side, it repeats the string `s` `n` times concatenating that. For instance:

nids@crimson: ~/Test/Pick$ perl -E 'say "banana"x5' bananabananabananabananabanana nids@crimson: ~/Test/Pick$As we already said, there are 4 separated cases that cannot happen at the same moment, or better, there are 3 cases, because the «both divisible by 3 and 5» can be reduced to the chaining of «divisible by 3» and «divisible 5».

what we do in the code above is exactly using the operator `x`, the chaining and the fact that booleans are just integers.

Since booleans are just integers, we can use them on the right hand side of the `x` operator to multiply the strings that we want to print by 0 or 1 only. If we repeat a string 0 times, we are just discarding that: the expression `"Fizz"x!($_%5)` does repeat the string "Fizz" only 0 or 1 times, depending on `$_` being a multiple of 5 or not. The same applies to all the other cases and the output of each case is concatenated with the other in such a way that we can create the output string: the cases of 3 and 5 are not exclusive so we can write "Fizz", "Buzz" or "FizzBuzz" but they are both exclusive with the case in which a number is not a multiple of none of them and we just print it as it was inside the automatic variable `$_`.

All of this fits 67 characters. Can you do better than this? :¬)

## Conclusions

In this document we saw a nice way to implement the FizzBuzz program and we tried to make it as short as possible. We were able to do that in only 67 characters, or bytes if you prefer.

But the must important thing is that we had a lot of **fun**!

## Edit (2012-10-07 12.49 GMT)

One of the people visiting this page reported that there is a shorter version on Rosetta Code:

print 'Fizz'x!($_ % 3) . 'Buzz'x!($_ % 5) || $_, "\n" for 1 .. 100;

Stripping some spaces out of that and using `say` instead of `print`, we get to this:

nids@crimson: ~/Test/FizzBuzz$ perl -E 'say"Fizz"x!($_%3)."Buzz"x!($_%5)||$_ for 1..100' 1 2 Buzz 4 Fizz Buzz 7 8 Buzz Fizz 11 Buzz 13 14 FizzBuzz 16 . . . . . 97 98 Fizz Buzz nids@crimson: ~/Test/FizzBuzz$Which is only 47 characters! Really impressive!

The solution uses the same idea of our solution but it actually uses a trick more: it uses the `||` or to decide if it need to print the crated string or the original value. This actually is very smart because in Perl the empty string is equivalent to the boolean value `false`.

Bravo!