Wednesday, January 24, 2007

I noticed some traffic coming to my post on juggling from Using FizzBuzz to Find Developers who Grok Coding. Like me, the author is having trouble with the fact that 199 out of 200 applicants for every programming job can’t write code at all. I repeat: they can’t write any code whatsoever.

UPDATE: If you think that I just claimed that 199 out of 200 working programmers cannot code, stop immediately and either read my follow-up explaining the math, or read Joel’s article on why companies aren’t as picky as they think they are. Thank you.

So the author has decided to set the bar ridiculously low. As the post says:

I’ve come to discover that people who struggle to code don’t just struggle on big problems, or even smallish problems (i.e. write a implementation of a linked list). They struggle with tiny problems.
He gives an example of a “tiny” problem that is quite suitable for a phone interview:

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”.
One of the nice things about using a tiny problem is that anyone who has written actual code in the last six months will solve it in less than ten minutes. This is good because (a) it leaves more time for talking about important things, and (b) if the candidate can’t solve the problem you will find out right away and save yourself a lot of grief.

As you can imagine from a post like this, quite a few people have stepped forward with creative solutions. Here’s mine:
``# fizzbuzz.rb# see http://raganwald.github.com/2007/01/closures-and-higher-order-functions.htmldef compose *lambdas  if lambdas.empty?    lambda { nil }  elsif lambdas.size == 1    lambdas.first  else    lambda do |n|      lambdas.first.call(compose(*lambdas[1..-1]).call(n))    end  endenddef carbonation(modulus, printable_form)  i = 0  lambda do |n|    (i = (i + 1) % modulus) == 0 && printable_form || n  endendprint(((1..100).map   &compose(     carbonation(15, 'FizzBuzz'),      carbonation(5, 'Buzz'),      carbonation(3, 'Fizz'))).join(' '))``

Right away I think you want to be careful if you ever trot a solution like this out in an actual interview. Here are some of the things that could go wrong:
• The interviewer merely wanted to go through the motions of demonstrating you could program. Now she’s going to have to get into a discussion with you about how your solution works, which is irritating and wastes time that could have been invested more profitably on a design question;

• The interviewer might presume that you will always find the most indirect route to the destination and decide you belong in an ivory tower;

• The interviewer might not understand your solution at first glance but will make up for this by “bikeshedding” and grilling you about some minor nit like the failure modes of using `&&` and `||` instead of the `if` statement or the ternary operator;

• The interviewer might have just finished The Seasoned Schemer and grill you over why your solution doesn’t use the Y Combinator to implement `compose` (snap!).
Of course, some interviewers are just looking for an excuse to talk about technical issues and will not prejudge you in any way. Speaking for myself, I would laugh if you wrote something like this out. But then again, I once worked for someone who had won the second International Obfuscated C Contest.

Update: Don’t Overthink the Interview Either

If you are conducting an interview and you receive a cryptic answer, or an impossibly concise one-liner, or perhaps something like the above that is redolent of Higher Order Functions, do you embrace the candidate as a genius? Or perhaps avoid them as someone who cannot write clear, maintainable code?

Love to program but you need to use Java? Free your mind with A Little Java, a Few Patterns: The authors of The Little Schemer and The Little MLer bring deep and important insights to the Java language. Every serious Java programmer should own a copy.

I suggest the best answer is neither. Stay on track: you asked the question for the purpose of eliminating the 199 out of 200 that have absolutely no hope of ever producing working software. You have just identified that this person is the one in two hundred applicants who can actually code. Mission accomplished. You aren’t trying to get to HIRE or NO HIRE over the phone.

Invite them in for an interview: that’s the place where you can drill down and obtain their views on professional programming. Remember, this is a toy problem. Unless you load the question down with requirements that their answer resemble production code, why should you have any expectation that the candidate only knows one way to write software?

This is like trying to hire programmers who know both languages, FORTRAN and COBOL.

If you do ask them for production code, don’t be surprised if the best candidates decide not to work for you: they will rightly point out that FizzBuzz is not a realistic example of a production problem.

Overall I think the best approach as an interviewer is the simplest: pose the simple question. Indicate it is a screener designed to confirm that they are the person described on the resume.

If anything, tell them that there is no need for production artifacts like documentation and unit tests, you just want working code in as little time as they are able. The no-hopers won’t get it no matter how simple the question, and the good people won’t waste a lot of time with JavaDoc and xUnit.

And then make your decision based on one objective fact: does the code run and produce the desired output. Everything else is superfluous to the question of whether the candidate should be asked into your office for a face-to-face meeting.

Update: a response to some of the criticism.

Labels: , ,

perl -e 'for my \$i (1..100) { my \$word = (\$i % 3) == 0 && (\$i % 5) == 0 ? "FizzBuzz" : (\$i % 3) == 0 ? "Fizz" : (\$i % 5) == 0 ? "Buzz" : \$i; print "\$word "; } print "\n"'

199 out of 200 seems high, but there you have it.

1 100 to ( 15 mod =0),( 3 mod =0),( 5 mod =0):'FizzBuzz','Fizz','Buzz'

Seems like a bit much for a phone interview, my throat would get sore going "right parenthesis, right parenthesis..." - maybe email?

199 out of 200 is not high. Try the following exercise:

Compose some reasonable resumé filtering criteria. For example, two or more years of Java experience, Bachelor's degree in Comp.Sci.

Perform a Monster search. Do you think that more than one out of the two hundred can dash a quick solution to "FizzBuzz" off the top of their head?

Now perfom the same exercize on a "control group" consisting of your colleagues. Compare results.

It does seem like a drag over the phone, but after you've had a morning where three straight applicants came in for an interview and failed, you don't want to see anyone else without them passing one or more of the five essential phone screen questions.

As for email as an alternative... I'm not sure. This definitely lets them go through hours of trial and error, so you can't judge whether they more-or-less get it right off the bat.

I don't care so much whether they get the braces right as I do whether they dash it off almost immediately.

This just in:

Someone claiming to be "Seth Gordon" wrote to say: My wife got me this for a birthday present, and I set it up in my cube. I was a little disturbed by how many of my co-workers couldn't figure out how to read it.

Seth, I deleted the comment. If this is on-topic in some way and not spamacious, please write back explaining the relevance and I'll be sure to let your comment through.

In the mean time, I must admit that a desk clock in binary does sound interesting, so I've modified the link to support the raganwald hosting costs.

Thanks for the idea.

My comment was meant to be continuing on the theme of "amazement at what so many people who code for a living can't figure out".

In fairness, I should also clarify that the people who were stumped by the clock were co-workers at a previous job.

C'mon! If you're going to do function composition in Ruby, you've got to define the * operator for the purpose. It's just too darn pretty to do it any other way. ;-)

Tom:

Actually, an earlier version overloaded + for this purpose. (I prefer to use * for producing the cartesian product of two functions).

However, I felt that the version with a compose method on Procs was a bit of a Platypus. It was a little Rubyish and a little Schemish, but not beautiful in either context.

I settled on writing a version that used a consistent SICP-sh philosophy.

I think if you're going to do the Ruby thing properly, you should do something clever with blocks rather than Procs. That just seems more Ruby-ish somehow.

in forth i wrote fizzbuzz here it is

: fizz? ( s -- f ) 3 mod 0= ;
: buzz? ( s -- f ) 5 mod 0= ;
: num? ( s -- ) dup fizz? swap buzz? or 0= ;
: ?fizz ( s -- ) fizz? if ." Fizz" then ;
: ?buzz ( s -- ) buzz? if ." Buzz" then ;
: ?num ( s -- ) num? if . then ;
: fizzbuzz ( s -- ) dup ?fizz dup ?buzz dup ?num cr ;
: fizzbuzzes ( s -- ) 1+ 1 do i fizzbuzz loop ;

The most factored fizz-buzz it only has 1 branch if statements and has all values factored and it is the fastest one.

If I were going to show off I would go for the low maintenance version:

(loop for i below 100
do (print (div-case i
((3 5) "fizzbuzz")
(3 "fizz")
(5 "buzz")
(otherwise i))))

where MOD-CASE is defined by

(defmacro div-case (form &body clauses)
(let ((n (gensym)))
`(let ((,n ,form))
(cond ,@(loop for (head . tail) in clauses
collect (cons (and-mod head n) tail))))))

with a helper function

(list `(zerop (mod ,n ,(reduce #'* head))))
((member t otherwise) t)))

Now the code is close to the spec and any-one can see how to make small modifications.

Just wanted to throw in some C# love to the crowd:

for(int x=1; x <= 100; ++x)
{
if(x % 3 == 0 && x % 5 == 0)
{
Console.WriteLine("FizzBuzz");
}
else
{
if(x % 3 == 0)
{
Console.WriteLine("Fizz");
}
if(x % 5 == 0)
{
Console.WriteLine("Buzz");
}
if(x %3 != 0 && x %5 != 0)
{
Console.WriteLine(x);
}
}
}

Are things /really/ that bad out there?

Real short in C too:

for(i=1 ; i < 101 ; i++){
printf("%d %s %s\n", i, i%3 ? "" : "fizz", i%5 ? "" : "buzz");
}

one liner in ruby, maybe a little long

puts (1..100).map{ |x| [x,["Fizz"][x%3],["Buzz"][x%5]] }.map{ |x| [x[0].to_s,x[1].to_s + x[2].to_s]}.map{|x| x.sort[x.length-1]}

ok, shorter version

puts (1..100).map{ |x| [["FizzBuzz","Fizz"],["Buzz",x]] [[x%3,1].min][[x%5,1].min] }

Kris: your solution isn't quite right, you shouldn't print out the number if you print out Fizz/Buzz.

Here's a really inappropriate oneliner solution in C:

char i,ii[3];
for (i=1;i<101;i++)
printf("%s%s%s\n",i%3?"":"Fizz",
i%5?"":"Buzz",
(i%3&&i%5&&sprintf(ii,"%d",i))?ii:"");

Man that's evil.

This post has been removed by the author.

Probably the cleanest, simplest way to solve it in ruby.

1.upto(100) do |x|
print x.to_s + " "
print "Fizz" if x % 3 == 0
print "Buzz" if x % 5 == 0
print "\n"
end

OMG.. like.. OMG,

I am a system admin, and I have always been very careful not to call myself a developer.. even though I can code fairly well (rusty as my "coding" usually is modifying someone else's to work how I want it too.) I can definatly design a program or system.. What you are saying here is that perhaps I should apply for Dev jobs?? It has been something I have never really done because I always figured good devs are all kick ass coders and I, by my own definition, am not but a okay one.. functional I should say..

food for thought..

Wow.. this gives me alot of insight into why the worst, most unrealistic users internally are the development department.

As for those who are all education happy.. well I have hired more then my fair share of university grads and I can say from experience that %99 of them are completely useless. A degree is a wonderful thing for advancement in management, but when you are looking for someone who can DO something, there is NO replacement for experience and the true hacker attitude and thirst for knowledge. If you want middle management drones, hire a University grad, if you want someone who is going to be Code Warrior, or a Systems Guru, hire someone who has been doing computers when they were 6 and live, eat and breath them day in, and day out.

The guys I know who I would call coders.. they code when they get up.. then go to work and code.. then come home (IF they come home) and code.. code code code... I gave up on Development years ago because I get WAY too obsessive. Still.. wouldn't mind getting out of what I am doing now, so I am sharpening up my Foo.. it is the FuzzBuzz test I should get the job it sounds like!

TTYL

I just gave my non-programmer wife a 5 minute Ruby lesson and she was able to write a FizzBuzz program in another 5. After spending the morning doing college-hire interviews and seeing evidence that a CS degree does not mean the ability to code, this is a depressing commentary on the state of CS education.

some Scheme

(define fizzbuzz (lambda(a b) (if (> a b)
(newline)
(fizzbuzzhelper a b))))
(define fizzbuzzhelper (lambda(a b)
(cond
((zero? (modulo a 15)) (display "FizzBuzz"))
((zero? (modulo a 3)) (display "Fizz"))
((zero? (modulo a 5)) (display "Buzz"))
(else (display a)))
(newline)
(fizzbuzz (+ a 1) b)))
(fizzbuzz 1 100)

Throwing in some java love!
(i'm 17 years old, taking AP Compsci in hs and the fact that 199/200 dont know how to program is a shame)

for(int c=0; c<101; c++)
{
if(c%3==0 && c%5==0)
{ System.out.println("FizzBizz"); }
else if(c%3==0)
{ System.out.println("Fizz"); }
else if(c%5==0)
{ System.out.println("Bizz"); }
else
{ System.out.println(c); }
}

gotta love java ;)

I dont know about how efficient my solution is, but its in PHP--CLI

for(\$i = 0; \$i <= 100; \$i++)
{
\$say = "";
if((!(\$i % 5)) || (!(\$i %3))) {
if(!(\$i % 3)){ \$say = "Fizz"; }
if(!(\$i % 5)) { \$say .="Buzz"; }
} else {
\$say = \$i
}
echo \$say . "\n";

private static void BuzzMyFizzBaby()
{
string o = "";
for (int x = 1; x < 101; ++x)
{
if ((x % 3) = 0)
{
if ((x % 5) = 0)
{
o = "FizzBuzz";
}
else
{
o = "Fizz";
}
}
else
{
if ((x % 5) = 0)
{
o = "Buzz";
}
else o = x.ToString();
}
Console.WriteLine(o);
}
}

Here’s my version done in javascript:

<script>

for(i=1; i<101; i++){

if(i%15==0){
document.write(”FizzBuzz<BR>”);
}else if(i%5==0){
document.write(”Buzz<BR>”);
}else if(i%3==0){
document.write(”Fizz<BR>”);
}else{
document.write(i+”<BR>”);
}

}

</script>

here we go in ActionScript

for (var a:Number = 0; a<100; a++) {
if (a%15 == 0) {
trace("Fizz-Buzz");
} else if (a%5 == 0) {
trace("Buzz");
} else if (a%3 == 0) {
trace("Fizz");
} else {
trace(a);
}
}

or

for (var a:Number = 0; a<100; a++) {
trace(a%15 == 0 ? "Fizz-Buzz" : a%5 == 0 ? "Buzz" : a%3 == 0 ? "Fizz" : a);
}

I love this language lol...

Here's my php version:

for (\$i=1;\$i<101;\$i++)
echo (\$i%3&&\$i%5)?\$i:'',
\$i%3?'':'Fizz',\$i%5?'':'Buzz',"\n";

Java bitch!

for(int i=1;i<51;i++) System.out.printf("%s\n",i%3==0&&i%5==0?"FizzBuzz":i%3==0?"Fizz":i%5==0?"Buzz":i);

The assertion that less than .5% of "Progammers" cannot get this correct is absolute poppycock. I performed this test on my 10 of my developers and ALL of them got it correct - most in less than 2 mins. Once again - a blogger making up a stat and trying to pass it off as fact.

The assertion that less than .5% of "Progammers" cannot get this correct is absolute poppycock.

I agree, and have always agreed.

I didn't assert this, and neither did Joel Spolsky in his post.

Have a closer look at the first paragraph. If you like, have a look at my response to some criticism.

my version in c#
for (int j = 1; j <= 100; j++)
{
string _write = ((j % 3 == 0) && (j % 5 == 0)) ? "FizzBuzz" :
(j % 3 == 0) ? "Fizz" : (j % 5 == 0) ? "Buzz" : j.ToString();
Console.WriteLine(_write);
}

Slightly cleaner C# version

class C
{
static void Main()
{
for(int i=1;i<101;i++)
{
System.Console.WriteLine((i%15==0)?"FizzBuzz":(i%5==0)?"Buzz":(i%3==0)?"Fizz":i.ToString());
}
}
}

1.upto(100) do |num|
str = ""
str += "Fizz" if num % 3 == 0
str += "Buzz" if num % 5 == 0
str += num.to_s if str == ""
puts str
end

Okay, so you've got it working. So now optimise for size... :-)

http://golf.shinh.org/p.rb?FizzBuzz

This post has been removed by the author.

Wow! I'm am so amazed at how many people (coders) are checking for 3 & 5 and outputting "FizzBuzz".

Pseudo-like code ;)...
loop num 1 to 100
hit = 0
if num mod 3 == 0, out "Fizz", hit=1
if num mod 5 == 0, out "Buzz", hit=1
if no hit, out num
end loop
// Note: if num is div by 3 & 5 "fizzbuzz" will auto display

I guess the best message to extract from these articles/discussions is that coders should not under estimate themselves. There are plenty of "coders" out there, but not many can code like you. :)

This post has been removed by the author.

FizzBuzz solution in J

FB=:((0 i.~15 3 5|]){::'FizzBuzz';'Fizz';'Buzz';":)"0
FB i.100

This is a tacit or functional solution, as the input parameter (number of integers to print) is not specified in the function FB. The function FB is defined in the first line, and invoked in the second line. The right argument of FB in the second line simply generates all the integers between 0 and 99.

Man, you programmers are out there. I'm not even sure if you're speaking English. I could participate by throwing in some lawyerese like, "the party of the first part assigns all rights, interests, claims, actions, suits, or entitlements, now existing or accruing in the future, to the party of the second part and forever waives, releases, relinquishes, and foregoes any recourse for itself, its assigns, successors in interest, officers, directors, representatives, employees, or other interested party..."

Actually, there is some relationship to coding here because a misplaced or omitted comma can change the entire agreement -- much like a missing paren. or tag can cause errors.

The sad part is that I went looking for a solution to a plugin issue I have on my blog and got so caught up in the FizzBuzz discussion that I had to see what a solution looked like. I freely admit it. I would not have been the 1 person who came up with the solution off the top of his head, but then, I highly doubt I would have said that I could on any resume. Unfortunately, I have just spent about an hour reading stuff because I found it interesting rather than a) solving my plugin problem; b) doing real work for which I would like to be paid; or c) going home and eating dinner. This to me is the REAL danger of Google. It's too diversion-friendly.

Instead of using i%3==0, use i%3<1, it cuts down on a bit of space.

While I agree with all Raganwald's points I think there are a lot of reasons why you should over-think FizzBuzz, enough to make an entire post on the subject.

Many of these 'here is the stuff in my no1 language of choice' comments really just differ in how the print function/method/routine is called. Really. I so needed to read that. Thanks.

Eversman I presume! - that's exactly how I ended up here too! And, no, I have no idea what this is about either. But it is interesting, that I stumbled into this dark pit of cabalistic babble only to find traces that another human had passed here before - it made me feel like I was on a journey to the centre of the Earth. ;) as they type...

Haven't seen any python code yet. Maybe because it doesn't look nice with out the indentation

m = {(True, False): "Fizz",
(False, True): "Buzz",
(True, True): "FizzBuzz"}

def fizzbuzz():
for i in range(1, 101):
k = (i % 3 == 0, i % 5 == 0)
if k in m:
print m[k] + " ",
else:
print str(i) + " ",

Rather late, but almost a one-liner on my term:
perl -e'for(1..100){
my\$h;
\$_%3||(\$h="Fizz");
\$_%5||(\$h.="Buzz");
print\$h?"\$h\n":"\$_\n"
}'

at least if you remove the line breaks.

hmmm raganwald ... I think you are one of the 199. Thinking you are above average because of this example is proof you are not. You probably learn this in your n00b tech school.

Anonymous:

So nice of you to drop by and share your charming argot with us.

You are correct that writing code like the example provided is not evidence of brilliance. That's actually what the post says, please read it again, and one more time if it doesn't seem clear.

Furthermore, getting the problem right in the strict sense of a program that produces the correct output does not place you in the top .5%, nor does it make you above average. The Update in the second paragraph supplies the explanations for why this is the case.

I suspect you have failed to realize we are actually in agreement. In the interest of exchanging colloquialisms, I wonder if you have scored an "own goal."

Thanks for the nice post!

I'm very late, i know ... a very short python version

for i in range(1, 100): print "%s%s"%((i%3==0) and "Fizz" or "", (i%5==0) and "Buzz" or "") or i,

another oneliner C# version in under 2 mins (including creating a new project and assuming console output..)

for(int i = 1; i <= 100 ; i++)
Console.Write(string.Format("{0} ", (i%3==0&&i%5==0)? "fissbuzz " : (i%5==0)?"buzz": (i%3==0) ? "fizz" : i.ToString() ));

Most people reading this will be horrified at the thought of so many students having so little to offer. I would think it is time to start questioning the tutors of their universities/colleges under the sale/provision of goods and services act (or relevant law in said country) perhaps

The fun thing is, everyone is using 3 strings, here's my attempt:

for (int i = 1; i < 101; i++)
{
string fizzBuzz = (i % 3) == 0 ? "Fizz" : string.Empty;
fizzBuzz += (i % 5) == 0 ? "Buzz" : string.Empty;
Console.WriteLine((fizzBuzz != string.Empty) ? fizzBuzz : i.ToString());
}

Just to feel confident.
Here's my Scheme version. It's two lines longer than that solution above, but it has some difference. Actually I didn't see the solution above before working out this one.

(define (fizzfuzz lst)
(if (not (eq? lst ()))
((lambda (x)
(display (cond ((zero? (modulo x 15)) 'fizzfuzz)
((zero? (modulo x 3)) 'fizz)
((zero? (modulo x 5)) 'fuzz)
(else x)))
(display "; ")
(fizzfuzz (cdr lst))) (car lst))))
(define (make-list a b)
(if (>= b a)
(cons a (make-list (+ a 1) b))
()))
(fizzfuzz (make-list 1 100))

Better late than never.... Here's an erlang solution:

-module (fizzbuzz).
-export ([fizzbuzz/0]).

print(N) -> io:format("~p~n", [N]).

fizzbuzz(101) -> ok;
fizzbuzz(N) when N rem 5 =:= 0, N rem 3 =:= 0 -> print("FizzBuzz"), fizzbuzz(N+1);
fizzbuzz(N) when N rem 5 =:= 0 -> print("Fizz"), fizzbuzz(N+1);
fizzbuzz(N) when N rem 3 =:= 0 -> print("Buzz"), fizzbuzz(N+1);
fizzbuzz(N) -> print(N), fizzbuzz(N+1).

fizzbuzz() -> fizzbuzz(1).

java code:
boolean isNotFizzy = false;
for(int i = 1; i < 101; i++){
if(i%5 == 0){
isNotFizzy = true;
if(i%3 == 0)
System.out.println("FizzBuzz");
else
System.out.println("Buzz");
}
if(i%3 == 0)
{
isNotFizzy = true;
System.out.println("Buzz");
}
if(isNotFizzy){ System.out.println(String.valueOf(i));
isNotFizzy = false;
}
}

Mark Kenneth Rañosa

This post has been removed by the author.

10 for i=1 to 100
20 if i mod 3 = 0 then goto 100
30 if i mod 5 = 0 then goto 200
40 print i
50 goto 400
100 if i mod 15 = 0 then goto 300
110 print "fizz"
120 goto 400
200 print "buzz"
210 goto 400
300 print "fizzbuzz"
400 next

I just found this today, and spent way too much time over-thinking fizz-buzz. I love seeing the functional ruby code ( because i don't fully grok the functional code yet, but dream in ruby ). But I think it took me a while to understand your solution because it is broken. The "carbonation" is dependent on starting at zero. It creates a function that accepts "n" then constructs the "n"from "i"? try this for range (2..101) you'll see what I mean. But still a good blahg-post, got me thinking.

(define (fizzbuzz end start)
(if (<= start end)
(let*
((three (zero? (modulo start 3)))
(five (zero? (modulo start 5)))
(both (and three five)))
(cond
(both (print "FizzBuzz"))
(three (print "Fizz"))
(five (print "Buzz"))
(else (print start)))
(fizzbuzz end (+ start 1)))))

(fizzbuzz 100 1)

(1..100).each {|i| [i,(i%3 == 0) && "Fizz",(i%5 == 0) && "Buzz", "\n"].each { |v| print v if v } }

for(\$i=1; \$i<101; \$i++)
echo ((!(\$i%3))?"fizz":"").((!(\$i%5))?"buzz":"");

booya!

alias fizz {
window @x
var %ù 0
while (%ù <= 100) {
if (!\$calc(%ù % 15)) { echo @x FizzBuzz }
elseif (!\$calc(%ù % 3)) { echo @x Fizz }
elseif (!\$calc(%ù % 5)) { echo @x Buzz }
else { echo @x %ù }
:w
inc %ù
}
}
:x

This is in PHP:

==========================
for(\$i=1; \$i<=100; \$i++){
if(\$i % 3 == 0) \$ct[\$i] = "Fizz";
if(\$i % 5 == 0) \$ct[\$i] .= "Buzz";
if(\$ct[\$i] == "") \$ct[\$i] = \$i;
}
==========================

I find your statistics pretty appalling - but that's one of the reasons I got out of full time programming (I still do some freelance work). Among other things, I got tired of cleaning up messes that other "programmers" had made and surprisingly, or maybe not so surprising to you, many of them had pretty impressive educational credentials.

Bah! I'm off to get a bottle of FizzBuzz ... err, I mean Coke.

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

Poor specs like this are a problem. Lets look at:

1) It makes the reader believe that multiples of 5 should be replaced with "Buzz" but doesn't clearly state it.

2) Through normal logic one would assume that 'FizzBuzz' is the result of 3 & 5 having both passed,
but the spec doesn't state that either. The person has interpret it their own way which is bad practice,
so instead he/she has to waste time/energy to get in touch with the designer to reclarify the design they
should have written properly in the first place

3) There are quotes used in the spec without the commonly used 'without the quotes' statement which means
it is fair to print the full terms.

At any rate, here is what this specs asks for (in php):

\$buffer = null;
for (\$i = 1; \$i <= 100; \$i++) {
\$is3 = !(\$i%3);
\$is5 = !(\$i%5);
\$buffer .= \$is3 ? '"Fizz"' : \$i;
\$buffer .= \$is5 ? '"Buzz"' : null;
\$buffer .= \$is3 && \$is5 ? '"FizzBuzz"' : null;
}
echo \$buffer;

The number 15 isn't printed, but instead:

fizzbuzzfizzbuzz

Code works or it doesn't work. If the spec is crap then you're gambling.

If the interviewer gives foolish examples like that then I just hope I don't work on the same team with him.

Some people can't write specs just as some people can't design user friendly interfaces to their own software. At any rate
it is unfair to blame the outcome of poorly written specs on the people who had to try to make sense of them.

-Jeck

We didn't overthink it, but we made a game out of it :) We'll be silent on exactly which formula we used ...

Feel free to check it out
http://buzzyteam.wordpress.com/fizzbuzz

With all do respect to George. His Forth version is neither the best factored nor the fastest. This version is better factored, faster, and shorter.

: fizz ( n -- ? ) 3 MOD IF FALSE EXIT THEN TRUE ." Fizz" ;
: buzz ( n -- ? ) 5 MOD IF FALSE EXIT THEN TRUE ." Buzz" ;
: bazz ( n ? -- ) IF DROP EXIT THEN . ;
: fizzBuzz ( n -- ) CR DUP fizz OVER buzz OR bazz ;
: fizzBuzzes ( -- ) 1+ 1 DO I fizzBuzz LOOP ;

100 fizzBuzzes

A solution in Clojure:

(use 'clojure.contrib.str-utils)

(print (str-join ", "
(map (fn [num]
(condp
#(zero? (mod %2 %1))
num
(* 3 5) "fizzbuzz"
3       "fizz"
5       "buzz"
num))
(range 1 101))))

<< Home