Fizzbuzz Without Ifs in 90 Characters -- I'll Buy You a Beer if You Can Beat It
Yesterday I got nerd-sniped into solving the FizzBuzz problem without using if sentences.
Fizzbuzz, no ifs: [{0: "fizzbuzz"}.get(x%(3*5), {0: "fizz"}.get(x%3, {0: "buzz"}.get(x%5))) for x in range(3, 100, 3)+range(5, 105, 5)]
— Swizec (@Swizec) September 16, 2012
Unfortunately, a more careful inspection of the problem specification reveals this solution was incorrect.
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”.
Luckily, that’s a very simple fix:
# codegolf version (90 characters):
[{0:"fizzbuzz"}.get(x%(3*5),{0:"fizz"}.get(x%3,{0:"buzz"}.get(x%5,x)))for x in range(101)]
# slightly more readable:
[{0: "fizzbuzz"}.get(x%(3*5),
{0: "fizz"}.get(x%3,
{0: "buzz"}.get(x%5, x)))
for x in range(101)]There you have it, a solution to the fizzbuzz problem that relies on python’s interactive command line interpreter thingy to do the printing, shaving off 4 characters for print.
The “trick”, if it can be called that, is relying on the native get method to return the correct string or fall back to the default value, which checks for the next string in the if-then-else chain.
I wish never to see code like that in something I have to maintain. Ever.
The challenge
Your challenge, should you choose to accept it, is to produce a shorter fizzbuzz solution without using if sentences. I will buy a bottle of beer for the winner.
The best Scala solution so far is 106 characters, by @HairyFotr:
1 to 100 map(a=>println((a%3,a%5)match{case(0,0)=>"fizzbuzz"case(0,_)=>"fizz"case(_,0)=>"buzz"case _=>a})) /ccNo really, I will send a bottle of beer anywhere in the world if you write a shorter solution. Of course, if feasible, I would prefer to take you out for a beer than use snail mail
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)







Comments
Tomasz Nurkiewicz replied on Sun, 2012/09/23 - 1:01pm
Łukasz Wolski replied on Mon, 2012/09/24 - 3:52am
[{0:"fizzbuzz"}.get(x%(15),{0:"fizz"}.get(x%3,{0:"buzz"}.get(x%5,x)))for x in range(101)]
Will Fi replied on Mon, 2012/09/24 - 8:56am
What about ternary operator?
Groovy: 67 chars
(1..100).each{println((!(it%3)?'Fizz':'')+(!(it%5)?'Buzz':'')?:it)}
Gabe Schenz replied on Tue, 2012/09/25 - 10:44pm
Shamelessly stealing from your example... but the output does look prettier. (73 characters)
for i in range(101):print i,{0:'Fizz'}.get(i%3,'')+{0:'Buzz'}.get(i%5,'')Or working in bash or ksh (65 characters):
a=Fizz;b=Buzz;for i in {1..100};do echo $i${a[i%3]}${b[i%5]};doneGarcia Mario replied on Tue, 2012/09/25 - 4:57pm
in response to:
Will Fi
Almost Will !!!
But you're missing 'FizzBuzz'. Just replace the "it" at the end with 'FizzBuzz'. I have three different versions:
- 64 chars: (1..100).each{n->print"${!(n%3)?'Fi':!(n%5)?'Bu':'FizzBu'}zz\n"}
- 64 chars: (1..100).each{n->println"${n%3==0?'Fi':n%5==0?'Bu':'FizzBu'}zz"}
- 59 chars: 1..100>>{n->print"${n%3==0?'Fi':n%5==0?'Bu':'FizzBu'}zz\n"}
All right I may have cheated a little bit in the third, to make it work you just have to add first the following line:Will Fi replied on Wed, 2012/09/26 - 8:59am
in response to:
Garcia Mario
No, @Garcia Mario, mine is correct. It prints 'FizzBuzz' when the result is divisible by both, thus getting printed 6 times. Yours is printing either 'Fizz', 'FizzBuzz' or 'Buzz' everytime, and the number needs to be printed when it's not divisible by neither of the three.
http://groovyconsole.appspot.com/script/763001
It's getting the same result as in this one in rubyforge: http://fizzbuzz.rubyforge.org/
Garcia Mario replied on Wed, 2012/09/26 - 3:08pm
in response to:
Will Fi
@Will Completely right!!! I didn't read it carefully, my apologies :)
This time I've just done it using collections no ifs (not even the ternary operator). This time 103 chars of pure Groovy.
(1..100).each{n->print"${[([0:'fizzbuzz'][n%(15)]),([0:'fizz'][n%3]),([0:'buzz'][n%5]),n].find{it}}\n"}
Will Fi replied on Thu, 2012/09/27 - 10:25am
in response to:
Garcia Mario
@Garcia Mario
Ah! searching for an index in little maps!
Without ternary operators, the best i could is Groovy: 96 :
(1..100).each{a->println([(15):'FizzBuzz',(3):'Fizz',(5):'Buzz',(a):a].find{k,v->!(a%k)}.value)}
It searches the map for an entry whose key is divisible by the number from 1 to 100. I was trying to work on a solution to ignore the (15):'FizzBuzz' using findAll, but no luck so far :-)
Willie Wheeler replied on Fri, 2012/12/21 - 4:03pm
Late response, but Groovy in 61 characters:
(1..100).each{println((it%3?'':'Fizz')+(it%5?'':'Buzz')?:it)}
This is obviously just a slightly modified version of Will's solution.