<p><pre><code> 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
</code></pre>
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.
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.<p>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.<p>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.<p>Too many introductions to Haskell's abstractions are too abstract. Good on the author for finding away around that.
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.
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:<p><pre><code> for i in xrange(1,101): print (('' if i%3 else 'Fizz')+('' if i%5 else 'Buzz')) or i
</code></pre>
or the even more general:<p><pre><code> 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
</code></pre>
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:<p><pre><code> #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;
}</code></pre>
I recently challenged people to codegolf fizzbuzz (<a href="http://swizec.com/blog/fizzbuzz-without-ifs-in-90-char-i-will-buy-you-a-beer-if-you-can-do-better/swizec/5276" rel="nofollow">http://swizec.com/blog/fizzbuzz-without-ifs-in-90-char-i-wil...</a>)<p>The Haskell solution was really cool:<p>[max(show x)(concat[n|(f,n)<-[(3,"Fizz"),(5,"Buzz")],mod x f==0])|x<-[1..100]]<p>This is much simpler and it looks easier to extend as well.
The Ruby example that you recommending hiring because of, is overkill. Here is a better Ruby example:<p><pre><code> (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</code></pre>
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.<p>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.<p>For experienced ones, the way our company (<a href="http://aelogica.com" rel="nofollow">http://aelogica.com</a>) 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.
For more on monoids, see Brent Yorgey's paper _Monoids: Theme and Variations (Functional Pearl)_ at <<a href="http://www.cis.upenn.edu/~byorgey/pub/monoid-pearl.pdf>" rel="nofollow">http://www.cis.upenn.edu/~byorgey/pub/monoid-pearl.pdf></a>; (there's also a video of his talk at the Haskell Symposium at <<a href="http://www.youtube.com/watch?v=X-8NCkD2vOw>" rel="nofollow">http://www.youtube.com/watch?v=X-8NCkD2vOw></a>).
"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..."<p>Nonsense.. you call a simple loop with a couple conditions difficult?
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.<p>And why introduce monad comprehensions if you're just introducing monoids?
<p><pre><code> 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}
</code></pre>
Kind of boggles the mind sometimes to realize the crappy code people will write without thinking things through.
In CoffeeScript:<p><pre><code> 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</code></pre>
First of all a modulo is ultra expensive, one does not simply modulo 15 when they already modulo 3 and 5.<p>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.<p>Second the example written is code bloat à la java, writing tons of stuff for no reason.<p>Third Ruby is a beta prototype language that doesn't have any production ready implementation.<p>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.<p>I have to admit it's impressive how such a simple test can show so many failures in people's deep understanding of programming.
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.<p>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.