You should follow me on Twitter

PHP Code Golfing – ‘FizzBuzz’

May 8th, 2011 - 1:13 pm | 2 Comments | Code, Hacks, Projects

Back in 2007 I read an interesting article about programmers who can’t actually program, probably shocking to some but not to those that remember Sturgeon’s Law (90% of everything is crap). A quick glance at the program described and I already had the code floating around in my head, trivial for a seasoned programmer.

The description of the program is as follows:

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”.

Soon thereafter I discovered the concept of ‘code golfing’ and was intrigued. I quickly rationalized that it was the best ways to teach bad coding practices, but at the same time give invaluable insight into the infrequently used operations of the language – some that might one day save a lot of grief. Thus my spiral into madness began as I set out to make the world’s smallest working version of the trivial FizzBuzz in PHP. Drinking might have been involved in this decision.

Let’s begin with a clean example of FizzBuzz, coded in PHP, weighing in at 351 bytes:

<?php
// Simple FizzBuzzer by Lorin
for ($num = 1; $num <= 100; $num++) { 
    if ($num %3 === 0 || $num % 5 === 0) {	// is $num divisible by 3 or 5?
      if ($num % 3 === 0) echo 'Fizz';	// Modulus instead of division
      if ($num % 5 === 0) echo 'Buzz';
    } else echo $num; // otherwise display number
    echo PHP_EOL; // new line!
}
?>

Ok, easily readable – works fine. Now let’s golf, but I’ll skip to the conclusion since that’s why you’re here, isn’t it?

But before that, I’d like to note code that looks like the following rarely has any reason to exist other than being a personal challenge. The two major exceptions to this would be demo scene code, where the goals are quite similar to those of code golf, or where code space is at an extreme premium, which has become much less relevant these days.

Here’s the svelte 56 byte result, a 6.2x decrease in code base!

<?while($i++<100)echo$i%3?!$$i=$i:Fizz,$i%5?$$i:Buzz,~õ;

Let’s break down the code:

  • Instead of the standard PHP opening tag, <?php, I use the much debated short tag opener <?, which I personally prefer. Additionally opening short tags don’t require a trailing space or newline – saving 4 bytes. This option may not be enabled by default on your server.
  • PHP doesn’t require a closing tag when it’s the final element outputted, so a semicolon is used instead, saving a single byte. Not including closing tags is actually recommended in some circumstances!
  • All comments and whitespace are removed, and the variable is now a single character – we’re going for computer executability, not human readability.
  • Shortening the loop – this was the easiest of all the shorthands tricks which I use when banging out proof of concept code. It loops from 1 to 100, a neat off-by-one effect.
  • Ternary operators instead of ifs. Because modulus operators return 0 when ‘true’ I had to swap the functions. A previous, larger version utilized three stacked ternary operators it was painful to debug. Don’t stack ternary operators if you can help it.
  • A variable set within echo… is echoed. However adding ! makes it ‘falsey’, and therefore unechoed.
  • Variable variables, the epicenter of madness. Variable variables may be named ANYTHING, even normally ‘illegal’ variable names made up from numerals only. This means every time the code loops it not only does it create a new variable named after its own value ($1, $2, $3…), but it also consumes additional memory. This took me the longest to figure out and was only discovered with the help of a peer. Nightmarish stuff…
  • On servers with reduced warnings you may remove the quotes around ‘Fizz’ and ‘Buzz’, using unset constants instead of strings. This will generate errors in future versions of PHP.
  • What happened to the new line? It got bit flipped! Instead of PHP_EOL (7 bytes), "\r\n" (6 bytes) or a physical new-line ascii character (3 bytes), I utilize the ~ bitwise operator, inverting the ‘õ’ character into the new-line character. This was the biggest “AHA!” moment for me.  However it won’t work in UTF-8 encoded files, use ANSI encoding instead.

So there you have it, the smallest version of FizzBuzz possible in PHP, although I look forward to a day where it gets beat. No cheating by loading from external sources! :)

↑ Join the Discussion (2)
You can safely stop scrolling now.