header image

Several times a week I have to interview people for software engineering jobs. While some of the people I talk with are very smart and qualified, I have, on occasion, complained about the calibre of the average applicant to my wife (who is also a software engineer). So when she read about FizzBuzz she shot me an email.

I read the blog entry and then perused the solutions that people were posting in the comments. FizzBuzz is easy. It's trivial. People who call it the "Programmer's Stairway to Heaven" must learn bar chords way more easily than I do. Anyone who has ever read a book (or taken a class) on programming can whip out FizzBuzz in a jiffy. It's so easy that I don't quite understand the compulsion to post your solution in a blog comment (which, based on the number of people who do it, is strong).

Then I saw a link to a code golf site for FizzBuzz solutions. Code golf, for the uninitiated, is the practice of trying to optimize a program for a low number of bytes in the source code. Yes, FizzBuzz is uninterestingly easy. However, add the challenge of "...in as few bytes as possible" to the mix, stir in "using some offbeat langages" and season with a little healthy bit of competition... well you've now got a stimulating diversion to waste time on.

My first attempt at FizzBuzz was in C. I was quite innocent back in those days because I thought this was a pretty good attempt at a "small" solution:

char *x[]={"%d\n","Buzz\n","Fizz\n","FizzBuzz\n"};
main(i){
for(i=1;i<101;i++)printf(x[!(i%3)*2|!(i%5)],i);
}
(104 bytes)

This works by picking a printf format string out of an array based on the value of i in a loop -- pretty straightforward. It is possible to compress this (and other) code a bit more by removing some whitespace or newlines. Of course, I did so before submitting them the golf site. But in this webpage I'll take some liberties with whitespace in the interest of readability.

I showed this code to a co-worker (breadbox) saying something along the lines of "how can people be getting sub 80 byte solutions to this?!" He is an old hand at these golf contests and I don't remember his reply exactly but it ended with the word "grasshopper". We both began tossing the problem around and exchanging ideas... Allow me to say at this point that some of the very best ideas on this page are his.

Here's another try:

main(i){
for(;i<101;i++)
printf(printf("%s%s",i%3?"":"Fizz",i%5?"":"Buzz")?"\n":"%d\n",i);
}
(92 bytes)

Getting closer. Would you like to tour some of the features of this model? The trick here is to use the return value of printf to see if it actually printed anything. The innermost call to printf can dump out "Fizz", "Buzz", "FizzBuzz" or nothing. If it dumped nothing, the outermost call needs to chime in with a number. It also provides the newline no matter what. Also note the skipped initialization of i -- it's really argc and therefore already set to one.

Let's try to shave off a few more bytes...

main(i){
for(;i<101;printf("%d\n^@FizzBuzz\n^@Fizz\n"+"^@^D^@^@^N^@^H^N^@^@^N^H^@^N"[i%15],i++));
}
(82 bytes)

This is my favorite C solution. There are smaller ones but this one is the coolest. First, it is smaller than it looks because all those funky control characters are raw in the source code. It works by cramming all the printf format strings together into one giant string with embedded null terminators (^@). Then it uses a small offset to pick what part of the format string actually gets used by printf. Since the FizzBuzz pattern repeats every 15 numbers, I just pick a small offset in the form of a low valued ASCII byte from the second string and add it to the first one. Ugly and beautiful at the same time.

Well, you can trim off a few more bytes here and there. And I did. I think I had one around 80 bytes. But the smallest size on the site was still something like 73 bytes (amazing). It was in a moment of desperation that I turned to "cheating". You see, by this point I already had FizzBuzz fever and had come up with this nice little Perl program...

main(){
system("perl -le'print+(Fizz)[$_%3].(Buzz)[$_%5]||$_ for 1..100'");
}
(76 bytes)

Why not? I mean, who's to say what is really against the rules. You can actually trim off a few more bytes here if you know a lot about shell programming. Breadbox pointed out that you can use seq and some other flags to perl to save 3 more bytes. This must be what the leaders were doing, right?

Wrong. It turns out that the golf site blocks exec* system calls and this solution is invalid. It works. But it's not allowed. Damn!

I have to admit that I gave up on C at this point and turned my attention to other languages I learned in a misspent youth: Pascal and BASIC. Breadbox kept at it, though, and produced this beauty:

main(i){
for(;i<101;puts(i++%5?"":"Buzz"))printf(i%3?i%5?"%d":"":"Fizz",i);
}
(75 bytes)

Very nice. Clever use of puts to save on the newlines. As of now this is the smallest solution for FizzBuzz that I know of in C. However I also know that a 73 byte version exists as the leader on the C board of the golf site has 73. I'd love to see it.


As I mentioned earlier, I gave up on C and headed towards some old friends: Pascal and BASIC. BASIC was pretty straightforward (no pun intended) and as of the time I'm writing this I have the smallest solution on the golf site:

for i=1to 100a$=str$(i)
if!mod(i,3)?"Fizz";:a$=""
if!mod(i,5)a$="Buzz"
?a$next
(78 bytes)

Did you remember that you can use a ? for PRINT in BASIC?! It took me a while to pull that out of the mental archives. I'm sure someone clever out there will come up with an even better solution... if you do, send me an email!

The only way I know how to do it shorter in BASIC is invalid for the same reasons that the C version is:

system("perl -le'print+(Fizz)[$_%3].(Buzz)[$_%5]||$_ for 1..100'")


PASCAL was harder for me than BASIC. Here was my first try:

var s:array[0..1,0..1] of String=(("","Buzz"),("Fizz","FizzBuzz"));i:Byte=1;
begin while i<101 do begin Str(i,s[0,0]);
Writeln(s[Byte(i mod 3=0),Byte(i mod 5=0)]);
inc(i)
end;end.
(176 bytes)

Wow, this is so verbose. All these begin and ends are killing me. Also, like in C, declaring new variables is something to avoid. Maybe I should ditch the array?

var i:Byte;
begin for i:=1 to 100 do begin
if(i mod 3=0)then Write("Fizz");
if(i mod 5=0)then Write("Buzz");
if(i mod 3>0)and(i mod 5>0)then Write(i);
Writeln end end.
(163 bytes)

Well, better I guess. I thought a long time about how to condense that last if condition and came up with nothing. And there is still the begin/end stuff for the loop, too. And all those Write/Writelns add up. Even the damn thens all over the place are expensive. Wait... what's this section of the GPC manual about a preprocessor?! Well, well, well... Niklaus Wirth hold onto your hat because I propose a new language: abbreviated Pascal. It's just like the old Pascal except way more terse:

#define f(b)if(i mod b=0)then
#define w(g)Writeln(#g)else
var i:Byte;begin
for i:=1to 100do
f(3)f(5)w(FizzBuzz)w(Fizz)f(5)w(Buzz)Writeln(i)end.
(143 bytes)

This was my first crack at using the preprocessor to make Pascal less verbose. The bit about scrunching the "to" and "do" into the number ahead is another trick I figured out on the way. The compiler warns you about it but does keeps going. If you're not familiar with the # in the w macro, it just puts quotes around the parameter g for you.

I was quite proud of this one... it was in first place at the golf site and it looks nothing like Pascal. But breadbox stared at it for about 5 minutes and improved it by about 10 bytes... then he posted his solution and made me figure out what the hell he did. It took me a bit longer but I also came up with something better:

#define f(b,g)if(i mod b=0)then Writeln(#g)else
var i:Byte;begin
for i:=1to 100do
f(15,FizzBuzz)f(3,Fizz)f(5,Buzz)Writeln(i)end.
(128 bytes)

This currently stands as the smallest solution in "Pascal" at the golf site.


I've done Java and Perl too... My Java isn't the best on the site (yet) but here it is for the sake of completeness:

class f{public static void main(String[]z){
for(int i=1;i<101;i++)
System.out.println(i%3<1?i%5<1?"FizzBuzz":"Fizz":i%5<1?"Buzz":i+"");}}
(136 bytes)

I recently managed to get this down a little bit:

class b{public static void main(String[]z){
for(int i=1;i<101;i++)
System.out.println((i%3<1?"Fizz":"")+(i%5<1?"Buzz":i%3<1?"":i+""));}}
(134 bytes)

Interestingly, this next version works fine with my javac (1.5.0_07) but doesn't compile at the golf site. :(

class b{public static void main(String[]z){
for(int i=1;i<101;i++)
System.out.println((i%3<1?"Fizz":"")+(i%5<1?"Buzz":i%3<1?"":i));}}
(131 bytes)


My Perl is tied for the top spot. This was my first attempt in Perl:

@x=("","Fizz
","Buzz
","FizzBuzz
");print $x[!($_%5)*2|!($_%3)]||"$_\n" for 1..100
(83 bytes)

Clearly, this sucks. Next attempt -- idea stolen from a different co-worker (jimr).

print+($_%3?"":"Fizz").($_%5?"":"Buzz")||$_,"\n" for 1..100
(58 bytes)

And, finally, after much pondering, an improvement that lets me get rid of the ternary operators:

print+(Fizz)[$_%3].(Buzz)[$_%5]||$_,$/for 1..100
(48 bytes)

I learned about the $/ and print+ tricks from breadbox.


I've also written FizzBuzz in Haskell and FORTRAN but, since I don't know either language very well, my solutions are nowhere near the smallest on the site and probably not worth listing.


I recently read a blog where someone complained about people wasting time writing FizzBuzz solutions on golf sites. I have to say that I can't disagree more -- writing small programs makes you really learn the programming languages you are working with. It's a good mental exercise, encourages creativity and is a lot of fun.


An epilogue: I did not give up code golf like I intended to do after the fizzbuzz obsession. Rather I got involved in a new challenge which was to print out a certain 128 bits without having those bits in the source code. Like fizzbuzz, this seems like a silly thing and it is. But the 128 bits in question have some sort of meaning to people in the MPAA because they were once an HD-DVD key. I'm told that it's "illegal" to publish them on the web (though I seriously doubt that would stand up in court). But since I don't want to buck the system too hard you'll have to just run the code and see what it produces. Here are my efforts... I'm especially fond of the BASIC one:

for x=1to 16?val(bin$(asc(mid$(" \xfa\x12\x3\x9eu\xe4\\xd9BW\xc6dW\x89\xc1",x))-1))using"%08.f";next
(75 bytes)

This next one is C.

main(i){for(;i<144;)
putchar("01 "[("F\xc4\xb7\xcb\xe3\xda7\nV;\xda\xb8\xda\x88\x3"[i/8]>>i%8&1)+!(i++%9)]);}
(83 bytes)

This challenge lasted for one week and by the end I had a way to shave off two more bytes from that C version. But I didn't bother because breadbox already had a beautiful 76 byte version:

i=143;main(){for(;i--;)
putchar(i%9<8?48|"\xc0\x88Vc\xc5VA\xd8[\xe3t\x9d\x2\x11\xf9\x9"[i/9]>>i%9&1:32);}
(76 bytes)

The only other ones I wrote were Pascal and Perl. Neither is very good (though no one else bothered to write a Pascal version so I guess it is, by definition, "good enough"):

program f;var i:Byte;
s:String="\x90\x9f\x88@\xb9.\xc7\xdax82j\xa3\xc6j\x11\x3";
t:array[0..1] of String=(""," ");Begin for i:=8to 135do Write(Byte(s[i div 8])shr(i mod 8)and 1,t[byte((i+1)mod 8=0)]);End.
(173 bytes)

See? I didn't even use the C preprocessor this time. I think that Pascal verion is totally beatable. Next is my Perl which also sucks:

$y="\xc0\x88Vc\xc5VA\xd8[\xe3t\x9d\x2\x11\xf9\x9";
print unpack("B8",$x)." "while($x=chop($y));
(68 bytes)

After one week everyone's code was opened up and I was very curious to see the best Perl entries. Here's one (again from breadbox):

print"@{[unpack'(b8)*','\x90\x9f\x88@\xb9.\xc7\xdax82j\xa3\xc6j\x11\x3']}"
(44 bytes)

Who knew that unpack could do that? The rest of it is apparently a way to put spaces between the successive elements of an array.

golf.html was last updated 19 July 2013 and is Copyright (C) 2002-2019 by Scott Gasch (scott.gasch@gmail.com).