
Fizzbuzz, Interviews, And Overthinking - timf
http://dave.fayr.am/posts/2012-10-4-finding-fizzbuzz.html
======
aristus

      cases = (
        (3, 'Fizz'),
        (5, 'Buzz'),
        (7, 'Bazz'),
        (11, 'Boo'),
        (13, 'Blip'),
      )
    
      for i in range(1, 101):
          out = []
          for c in cases:
              if i % c[0] == 0:
                  out.append(c[1])
          if out:
              print ''.join(out)
          else:
              print i
    
    

Edit: not to detract from the post's point, I think it's valid. Monoids are
cool and all but simple counting arguments can take you a long, long, long,
way when case analysis fails you.

~~~
sowhatquestion
This can be edited down to six lines with a simple trick: a Python string
multiplied by True will return itself, and multiplied by False will return the
empty string.

    
    
      for i in range(110):
          pr = ""
          pr += "Fizz" * (i%3 == 0)
          pr += "Buzz" * (i%5 == 0)
          pr += "Bazz" * (i%7 == 0)
          print (pr if pr else i)
    

I iterated over range(110) to show that it handles the "FizzBuzzBazz" case
correctly.

EDIT: Or we could use lambdas as OP's Ruby code did; this might be more
maintainable...

    
    
      cases = [
          lambda n: "Fizz" * (n%3 == 0),
          lambda n: "Buzz" * (n%5 == 0),
          lambda n: "Bazz" * (n%7 == 0) ]
    
      for i in range(110):
          pr = ""
          for case in cases:
              pr += case(i)
          print (pr if pr else i)
    

That's nine nonblank lines.

~~~
koblas
Just for fun, another variant - separating logic from data and trying to be
pretty stock python.

    
    
        cases = [(3, "Fizz"), (5, "Buzz"), (7, "Bazz")]
    
        for i in range(110):
            pr = ''.join([v[1] * (i % v[0] == 0) for v in cases])
            print pr or i

~~~
deadmansshoes
It should be possible in a single line of Python..

    
    
      pip install fizzbuzz
    

And then:

    
    
      import fizzbuzz
      print fizzbuzz.fizzbuzz()
    

Or for the second solution:

    
    
      print fizzbuzz.fizzbuzzbazz()

~~~
jonp
A tweetable (140 character) single line of Python:

print '\n'.join((lambda x:(''.join(x) if x else str(i)))([w+'zz' for (n,w) in
((3,'Fi'),(5,'Bu'),(7,'Ba')) if i%n==0]) for i in range(1,100))

------
rauljara
I understood from near the very beginning that this wasn't really about
Fizzbuzz. All the way through the post, I was waiting for the author to get a
real world example instead of Fizzbuzz. Yet, I got to the end of the post and
realized it was already pretty long.

I think in talking about programming, we are often hindered by the fact that
it is much more complicated than our brains can handle. Our only choices are
to write novel length treatments of real programs or short story length posts
about a toy program, or just the tiniest piece of a real program.

Which is all to say, as sick of hearing about Fizzbuzz as I am, I'm glad there
are silly little examples like it that we all know. Even though it was
ostensibly about interviewing, that was a much clearer introduction to monoids
than most. I think it was largely because it was in reference to Fizzbuzz:
something very concrete with which we're all familiar.

Too many introductions to Haskell's abstractions are too abstract. Good on the
author for finding away around that.

~~~
KirinDave
Thanks!

What sort of surprised me as I shopped my copy around and showed people the
python-add-one-factor example is that even programmers I consider experts
didn't realize how quickly the conditional cascade blows up. It's easy to
miss. And I looked around for people to mention this in blog posts, but almost
no one does. So I feel like there's a bit of life left in the old fizzbuzz
yet.

~~~
dspeyer
I think the non-blown cascade is exactly what makes fizzbuzz aggravating. With
three noises, the linear solution clearly dominates. With two, the exponential
is actually shorter -- but feels unclean.

~~~
jerf
I've been programming some game servers, and I have the same problem with
guaranteed two-player games; I feel dirty hard-coding the logic to assume two
players, yet making it general enough for N players makes it absurdly more
complex for no gain, which is a net loss.

(And yes, before anyone pops in, these are _guaranteed_ two-player games. Of
all the rules of the games in question which have changed over time, that is
the one rock-solid constant which will not change in this application.)

------
__david__
Forget Fizzbuzz, we get candidates that cannot reverse a string (in their
language of choice). A friend of mine just told me he uses the question "What
is the hex number that comes after 'F'" as his first "weed-out" technical
question. It boggles the mind.

~~~
KirinDave
Because I tend to get really nervous in interviews and consequently don't
interview all that well most of the time, I try to be sensitive to people like
me. I prefer to start very simple and sort of gradually increase the pressure
until I can find a backing off point.

~~~
adgar2
If you cannot reverse a string under pressure, you are likely unqualified for
the job you are applying for. At least in my job, there is often more pressure
than "write a string reverse function in any language you like in 10 minutes."

~~~
EnderMB
What a load of bollocks. If your job is to write methods to reverse strings
then you are unqualified, otherwise I wouldn't give a shit whether a candidate
can reverse a string. Why would I want to know if someone can reverse a string
if the job is to maintain a web app?

A few questions for you. How old are you? Have you hired developers before?
Truthfully, have you ever had to reverse a string under pressure at your
current job.

~~~
borplk
Are you kidding? reversing a string in your language of choice is far too
trivial. If you can't do it you really aren't ready to be working in the
industry.

~~~
EnderMB
It's not about whether they can do it or not. It's about why knowing a skill
that will take even a non-developer ten seconds to Google makes someone
incapable of functioning as a developer.

More often than not the people that spout that kind of nonsense are twenty-
something junior developers that read a bit of HN and have decided that they
know better than everyone else about what makes a good programmer.

Why would you test if someone can reverse a string if you're hiring someone to
maintain and build on some shitty web app?

~~~
candybar
It takes someone who doesn't speak English ten seconds to look up the past
tense of the verb "bring" - this doesn't mean you'd want to hire as a
journalist someone who seems to think the answer is "bringed"

Doing a string reverse is so trivial that it's not about needing that skill,
but rather what not being able to do that speaks about the candidate's general
aptitude and skill level.

~~~
EnderMB
"Why would you test if someone can reverse a string if you're hiring someone
to maintain and build on some shitty web app?"

If that question can't be answered then your opinion on someones skill level
is irrelevant. Also, if you've got time, answer the questions in my first
post:

"How old are you? Have you hired developers before? Truthfully, have you ever
had to reverse a string under pressure at your current job."

~~~
candybar
Because anyone who can't do this almost certainly doesn't have the ability to
program any software system well, some shitty web app or otherwise. You're not
trying to fill out a remedial CS course in community college, you're trying to
get someone to program real things real people use.

The only way this question wouldn't be useful is if you had a good filter such
that almost everyone who gets to that point would answer that question
correctly. But apparently, this is not the case. There are people who fail
such tests (despite apparently good paper qualifications and ability to talk
BS). It's fairly important that you not let through such imposters.

And yes I've hired people and all of them have had to answer much more complex
algorithmic questions to get the job and all of them turned out to be
competent. And "have you ever had to" questions are ingenuous - interview
settings are never going to be replicated exactly in a work setting, unless
your job is to go around to be interviewed for different jobs. Good interview
questions don't simulate work setting - they extract most critical work-
relevant information about the candidate without wasting time.

~~~
EnderMB
"Because anyone who can't do this almost certainly doesn't have the ability to
program any software system well, some shitty web app or otherwise. You're not
trying to fill out a remedial CS course in community college, you're trying to
get someone to program real things real people use."

So...I'm hiring someone that can reverse a string because this demonstrates
that they can program real things that real people use?

"And yes I've hired people and all of them have had to answer much more
complex algorithmic questions to get the job and all of them turned out to be
competent."

Out of interest, what did this job entail? I assume that you quizzed them on
their knowledge of basic algorithms because they are required to write them,
right?

------
absherwin
I agree that Fizzbuzz can be a more interesting example of how to write code
without repetition. While the author suggests that languages such as Haskell
provide a unique advantage, the deciding question seems to be the availability
of pre-built abstractions. Consider the following solution in Python:

    
    
      for i in xrange(1,101): print (('' if i%3 else 'Fizz')+('' if i%5 else 'Buzz')) or i
    

or the even more general:

    
    
      mapping={3:'Fizz',5:'Buzz'}
      for i in xrange(1,101): 
        print ''.join(['' if i%x else mapping[x] for x in mapping]) or i
    

We can even do this in C though to write something as extensible as the second
would require writing more helper functions than I can justify for this brief
comment:

    
    
      #include<string.h>
      #include<stdio.h>
      int main(){
        int i;
        char s[4];
        char n[3];
        for (i=1;i<101;i++){
          sprintf(n,"%d",i)
          s=strcat((i%3)?"":"Fuzz",(i%5)?"":"Buzz")
          printf("%s",(strlen(s))?s:n)
        }
        return 0;
      }

~~~
daeken
My "I'm going to hell, but that's okay" C version:

    
    
      #include <stdio.h>
      #include <stdbool.h>
    
      #define when(mod, msg) do { if((i mod) == 0) { fputs(#msg, stdout); *hit = true; } } while(0)
      #define through ; i <=
      #define engine(range) \
      void rules(int, bool *);\
      int main(void) { for(int i = range; ++i) { bool hit = false; rules(i, &hit); if(!hit) printf("%d", i); putchar('\n'); } } \
      void rules(int i, bool *hit)
    
      engine(1 through 100) {
        when(% 3, Fizz);
        when(% 5, Buzz);
      }
    

Super extensible!

~~~
KirinDave
I'm not sure even hell will take you after doing what you just did. There is
no metaphysical consequence great enough save to have experienced the writing
of that.

------
Swizec
I recently challenged people to codegolf fizzbuzz
([http://swizec.com/blog/fizzbuzz-without-ifs-in-90-char-i-
wil...](http://swizec.com/blog/fizzbuzz-without-ifs-in-90-char-i-will-buy-you-
a-beer-if-you-can-do-better/swizec/5276))

The Haskell solution was really cool:

[max(show x)(concat[n|(f,n)<-[(3,"Fizz"),(5,"Buzz")],mod x f==0])|x<-[1..100]]

This is much simpler and it looks easier to extend as well.

~~~
koblas
Python: under 90 characters and no explicits if statements

    
    
        for i in range(100):print ''.join([s*(i%m==0)for m,s in[(3,"Fizz"),(5,"Buzz")]])or i

~~~
osener
66 characters:

    
    
        " ".join(i%3/2*"Fizz"+i%5/4*"Buzz"or str(i+1) for i in range(100))

------
jisaacks
The Ruby example that you recommending hiring because of, is overkill. Here is
a better Ruby example:

    
    
        (1..100).each do |i|
          o = ""
          o.concat("Fizz") if i % 3 == 0  
          o.concat("Buzz") if i % 5 == 0  
          o.concat("Bazz") if i % 7 == 0  
          o.concat(i.to_s) if o.empty?  
          puts o
        end

------
pd_i
Great article. The title is a bit misleading though. I thought this was sort
of a counter-argument to the 'programmers cannot program', but introduces
monoids right at the end.

Anyway, FizzBuzz and the like are the kinds of questions you would probably
ask to a new graduate because frankly, there is nothing else to ask from them.
They have no related experience for the most part.

For experienced ones, the way our company (<http://aelogica.com>) identifies
good candidates is via a day of pair-programming. Technical knowledge is just
part of the package, and any kind of problem solving will not address that.

------
ostso
For more on monoids, see Brent Yorgey's paper _Monoids: Theme and Variations
(Functional Pearl)_ at <[http://www.cis.upenn.edu/~byorgey/pub/monoid-
pearl.pdf>](http://www.cis.upenn.edu/~byorgey/pub/monoid-pearl.pdf>); (there's
also a video of his talk at the Haskell Symposium at
<[http://www.youtube.com/watch?v=X-8NCkD2vOw>](http://www.youtube.com/watch?v=X-8NCkD2vOw>)).

------
romonopoly
"When you really boil it down to its implementation, FizzBuzz is something of
an irritating program. I’m not sure how much the author of the problem really
thought about FizzBuzz, but it turns out it’s difficult to express well with
the tools available to most imperative programming languages..."

Nonsense.. you call a simple loop with a couple conditions difficult?

------
adiM
I was waiting for a Java solution with an AbstractFactory somewhere.

~~~
LnxPrgr3
No AbstractFactory here, but there is XML! And 411 lines of Java:
<http://pastebin.com/TyNrvRmB>

------
nandemo
This seems overcomplicated. Why wrap String (which is already a monoid) inside
Maybe? You can just use concat; if the result is the empty string then print
the number. If you want it to work for any monoid, then use mconcat, and test
for equality to mempty.

And why introduce monad comprehensions if you're just introducing monoids?

~~~
KirinDave
> Why wrap String (which is already a monoid) inside Maybe?

Because it's a bit easier to write the tail end of the logic in generic terms.
You can go talk to c_wraith on Freenode#haskell if you want.

> You can just use concat; if the result is the empty string then print the
> number. If you want it to work for any monoid, then use mconcat, and test
> for equality to mempty.

You can find other discussions about why flexibility is important.

> And why introduce monad comprehensions if you're just introducing monoids?

Because it's a really nice syntax? Compared to explicitly using guard,
anyways.

------
judofyr
I've always liked the \r-trick:

    
    
        a=b=c=d=(e=1..100).each do |num|
          print num, ?\r,
            ("Fizz" unless (a = !a) .. (a = !a)),
            ("Buzz" unless (b = !b) ... !((c = !c) .. (c = !c))),
            ("Bazz" unless ((d = !d) .. (d = !d)) ... (e = !e)),
            ?\n
        end

------
SeoxyS

        subs = {3 => "Fizz", 5 => "Buzz", 7 => "Bazz"}
        (1..100).map{|n| subs.keys.inject(nil) {|a,k| n % k == 0 ? (a||"")+subs[k] : a} || n.to_s}
    

Kind of boggles the mind sometimes to realize the crappy code people will
write without thinking things through.

------
yjo
In CoffeeScript:

    
    
      divisors = {Fizz:3, Buzz:5, Bazz:7}
      for i in [1..100]
        alert (name for name,divisor of divisors when i % divisor == 0).join("") || i

------
scotty79
Monowha?

for(var i=1;i<=100;i++) console.info(((!(i % 3) ? "Fizz" : "") + (!(i % 5) ?
"Buzz" : "") + (!(i % 7) ? "Bazz" : "")) || i);

------
ludovicurbain
First of all a modulo is ultra expensive, one does not simply modulo 15 when
they already modulo 3 and 5.

The proper structure is if(3){if(5)}elif(5){}else{},unless anyone has a better
proposition. While of course it is possible to define abstractions that handle
fizzbuzzing anything for any number, it's clear that the monoid way is a bad
overweight bloated approach.

Second the example written is code bloat à la java, writing tons of stuff for
no reason.

Third Ruby is a beta prototype language that doesn't have any production ready
implementation.

Lastly functional and procedural programming enable you to work at the highest
level of abstraction you can think of, whereas OO tends to lock you at a
specific abstraction level, which is pretty low and not adapted to most cases.

I have to admit it's impressive how such a simple test can show so many
failures in people's deep understanding of programming.

~~~
KirinDave
This is another example of someone who I think looked at my code examples but
didn't read the post. Fair enough, I guess.

> While of course it is possible to define abstractions that handle
> fizzbuzzing anything for any number, it's clear that the monoid way is a bad
> overweight bloated approach.

Why? It is not computationally expensive, and it avoids excess modulo
operations. All the dispatching work gets figured out at compile time and you
end up with pretty much the same sorts of string concatenation costs you get
in every other implementation.

Do you mean to suggest that it is conceptually expensive?

> Lastly functional and procedural programming enable you to work at the
> highest level of abstraction you can think of, whereas OO tends to lock you
> at a specific abstraction level, which is pretty low and not adapted to most
> cases.

I actually agree with this, although I sort of question procedural's place on
the totem. I suppose stuff like Forth suggests you're right.

~~~
ludovicurbain
Bloated, as in, takes way too much space for what it is.

Additionally, it does _not_ avoid excess mod operations, _and_ the
implementation is _broken_ because it won't print fizzbuzz for the 15.

Lastly, using lambda's and whatnot's just because you can is yet another form
of inefficiency and completely obfuscates what the machine will do.

I mean to suggest that 1) it should be a much shorter read 2) it's
inefficient, and wrong 3) one does not simply lambda everything.

~~~
KirinDave
> Bloated, as in, takes way too much space for what it is. > Additionally, it
> does _not_ avoid excess mod operations, _and_ the implementation is _broken_
> because it won't print fizzbuzz for the 15.

If we're talking about the Haskell version here (I can't tell?), you're wrong
on all counts.

• It is about as short as any reasonable impl I've seen of FizzBuzzBazz. Not
long at all.

• And it _does_ print out correctly for 15.

• And it does NOT do excess operations. It does exactly one modulo per factor.

Do you not understand how it works? I detail it pretty closely in the post;
please look again.

The second ruby version _is_ long, but does not perform excess operations
(unless you're complaining about Ruby's implementation of lambdas, which is
out of scope). As I said both in my article and in this discussion; coding
during an interview is tricky and that's not a bad effort.

Fianlly, the naive if-chain extensions are deliberately wrong to extend, but
my initial research and experience is that most programmers don't realize that
until they try it once. But then, they're lifted right from Rosetta Code so
they're hardly unrepresentative of what people consider an "unacceptable"
version of Fizzbuzz.

------
droithomme
We're five years into this, and here's yet another weekly column from a person
who has just heard about it and is champing at the bit to prove both he can
write FizzBuzz and all the other implementations are not as good as his. It
will be a miracle if this thread doesn't turn into a chain of "even better"
solutions, like all the other threads that came before it.

In this week's installment, the variation where it is claimed that common
production languages are inadequate for a problem of this complexity, and the
tool stack should be shifted to languages supporting monads... er monoids?
Sigh.

~~~
rprasad
I would prefer to force candidates to implement FizzBuzz in a language
invented solely for purposes of that interview (and which will never be used
again). This places all candidates on the same level.

It's probably a good thing I don't interview people for programming
positions...

~~~
jerf
You have so little time in an interview to learn so much you can't afford to
lose the time to both learn whether they can do FizzBuzz (or whatever other
problem) and whether they can manipulate some language of interest, when you
could be learning both

The purpose of an interview isn't to be abstractly "fair", it's to find the
best candidates for the job. You choose what "best" is (which is to say,
please don't put words in my mouth about "only interviewing for the exact
skillset" or whatever... _you_ choose what is best, whatever that is). My
preferred approach is to give the problem, then let the candidate write in
whatever language they choose. If they flail in their putatively favorite
language with which they've putatively been working for 4 years... well...
I've certainly learned some very important things in those few moments.

~~~
rprasad
I thought it was pretty clear based on the second sentence that the comment
was intended as a joke. Do I really need to start adding /jk to the end of my
comments?

~~~
jerf
Sorry. I've heard the idea seriously proposed elsewhere.

