FizzBuzz (#126)

So: much like Marcel Proust biting into a madelaine, when I read this
quiz on
Friday I had a rush of old memories. I have never heard of fizzbuzz
being
used as a recruitment technique before, however, I am familiar with it
because back in high school we played it as a drinking game. If we were
feeling particularly hardcore we would also add in ‘Bang’ for multiples
of 7.
I had as much as forgotten about fizzbuzz as I haven’t though about it
in
over twelve years or so…

Anyway, I have deviated from the official spec in a few ways here. First
of
all, I saw no reason to stop at 100, so my solution will print results
for
any user-specified ‘n’. Rather than golfing, which I am no good at, I
decided
to go with an obvious solution.

The second deviation is that because the solution is fairly short (ie:
about a
paragraph) I thought it would be interesting to write solutions in a few
other languages as a point of comparison. To that end I also wrote
solutions
in Python, Lua, Scheme, and plain old C. Hopefully you can forgive me
some
off-topicness for posting these as well.

On with the code:

fizz.rb

1.upto(ARGV[0].to_i) do |n|
if n % 15 == 0
print "FizzBuzz "
elsif n % 5 == 0
print "Buzz "
elsif n % 3 == 0
print "Fizz "
else print "#{n} "
end
end
puts

fizz.py

import sys
for n in range(1,int(sys.argv[1])+1):
if n % 15 == 0:
sys.stdout.write("FizzBuzz ")
elif n % 3 == 0:
sys.stdout.write("Fizz ")
elif n % 5 == 0:
sys.stdout.write("Buzz “)
else: sys.stdout.write(”%i " % n)
print

– fizz.lua
for n=1,arg[1] do
if n % 15 == 0 then
io.write("FizzBuzz ")
elseif n % 3 == 0 then
io.write("Fizz ")
elseif n % 5 == 0 then
io.write("Buzz ")
else
io.write(n … " ")
end
end
print()

/* fizz.c */
#include <stdio.h>

int main(int argc, char *argv[]) {
int i;
for (i = 1; i <= atoi(argv[1]); i++) {
if (i % 15 == 0)
printf("%s “, “FizzBuzz”);
else if (i % 3 == 0)
printf(”%s “, “Fizz”);
else if (i % 5 == 0)
printf(”%s “, “Buzz”);
else
printf(”%i “, i);
}
printf(”\n");
return 0;
}

;;; fizz.scm
(define (fizz x)
(define (mod5? n)
(if (eq? (modulo n 5) 0) #t #f))
(define (mod3? n)
(if (eq? (modulo n 3) 0) #t #f))
(define (fizz-iter n x)
(cond
((> n x) (newline) #t)
((and (mod3? n) (not (mod5? n))) (display "Fizz ")
(fizz-iter (+ n 1) x))
((and (mod5? n) (not (mod3? n))) (display "Buzz ")
(fizz-iter (+ n 1) x))
((and (mod5? n) (mod3? n)) (display "FizzBuzz ")
(fizz-iter (+ n 1) x))
(else (display n) (display " ")
(fizz-iter (+ n 1) x))))
(fizz-iter 1 x))

cheers,
-d

On Jun 3, 2007, at 11:47 AM, Daniel M. wrote:

Well, it’s been nice talking to you, Mr. Martin, and I thank you for

your interest in CompuGlobalMegaTech. We’ll be in touch over the

next

few days with our decision.

They would be a fool not to hire you. :wink:

James Edward G. II

Ruby Q. [email protected] writes:

Pretend you’ve just walked into a job interview and been hit with
this question. Solve it as you would under such circumstances for
this week’s Ruby Q…

Well, Mr. Martin, this is just a simple little question we ask all of

our programming candidates. Let’s see what you do with “FizzBuzz”:

(1…100).each{|i|
x = ‘’
x += ‘Fizz’ if i%3==0
x += ‘Buzz’ if i%5==0
puts(x.empty? ? i : x);
}

Okay, very straightforward. You know, I’ve never been an overly big

fan of the question mark-colon operator. It always seemed to me one

of the constructs in C most open to abuse.

What’s that? Oh, okay, so how would you eliminate that ?: in favor

of something more Rubyish?

(1…100).each{|i|
x = i
x = ‘Fizz’ if i%3==0
x += ‘Buzz’ if i%5==0 rescue x=‘Buzz’
puts x;
}

Well using “rescue” certainly does feel more Rubyish.

It says here that you’ve done significant work with functional

languages. Could you rewrite this to take advantage of higher order

functions?

a = [proc{|x|x}, proc{|x|x}, proc{:Fizz}] * 5
a[4]=a[9]=proc{:Buzz}
a[14]=proc{:FizzBuzz}
(1…100).zip(a*9){|i,l|puts l[i]}

Well that’s rather cryptic, and I don’t necessarily like the manual

computation behind the indexes 4, 9, and 14. I’d prefer something

that, like your first two solutions, combined the Fizz and Buzz so

that the FIzzBuzz printed every fifteen spots is a natural

consequence.

f = proc{‘Fizz’}
b = proc{|x|x+‘Buzz’ rescue :Buzz}
i = proc{|x|x}
(1…100).zip([i,i,f]*99,[i,i,i,i,b]*99){|n,p,q|puts q[p[n]]}

Uh… yes. In that I can see the two cycles, the 3-cycle and the

5-cycle, but I’m not sure that turned out as clear as I had hoped.

I wonder if a hybrid approach where you used anonymous functions

only for one of the two words is worth considering…

b=proc{|i,s|i%5==0?s+‘Buzz’:s rescue :Buzz}
puts (1…100).map{|i|b[i,i%3==0?‘Fizz’:i]}

There’s that ?: operator again.

You know, you aren’t really using arbitrary functions there. I wonder

if lambda functions aren’t overkill for this problem. What if you

repeated the pattern where you showed the two cycles, but used simple

strings instead?

$;=‘/’
(1…100).zip(‘//Fizz’.split99,‘////Buzz’.split99) {|a|
puts((‘%d%s%s’%a).sub(/\d+(?=\D)/,‘’))}

Well, okay, you’ve shown that sometimes strings are not as easy to

read

as one might think.

I noticed you using a regular expression there and I note that your

resume shows extensive experience with regular expressions. That’s a

rather small example on which to judge your regular expression

experience. Could you somehow make more use of regular expressions?

(1…100).map{|i|“#{i}\n”}.join.
gsub(/^([369]?[0369]|[147][258]|[258][147])$/m,‘Fizz\1’).
gsub(/\d*[50]$/m,‘Buzz’).gsub(/z\d+/,‘z’).display

Let us never speak of this again.

Well, Mr. Martin, I think you’ve shown technically what we’re looking

for. Tell me, do you golf?

puts (1…100).map{|a|x=a%3==0?‘Fizz’:‘’;x+='Buzz’if a%5==0;x.empty??
a:x}

Uh, that

puts (1…100).map{|i|[i,:Buzz,:Fizz,:FizzBuzz][i%5==0?1:0+i%3==0?2:0]}

Mr. Martin, that’s not

puts (1…100).map{|i|i%15==0?:FizzBuzz:i%5==0?:Buzz:i%3==0?:Fizz:i}

I, uh, hadn’t meant that kind of golf.

(Though, as an aside, you could save characters by using 1.upto(100)

and by using <1 in place of ==0)

However, these last few examples bring home a point I was worrying

about

before that we haven’t really touched on yet - all of these have

varying degrees of readability, yet Ruby is supposed to be an

eminently

readable language. How could you make this code more readable?

puts (1…100).map{|i|
case i%15
when 0 then :FizzBuzz
when 5,10 then :Buzz
when 3,6,9,12 then :Fizz
else i
end
}

Well, that certainly is an improvement, though separating the “puts”

from the rest of the logic might be slightly confusing and I’d prefer

a more direct translation from the English program specification to

the code.

(1…100).each {|i|
if i%5==0 and i%3==0 then puts :FizzBuzz
elsif i%5==0 then puts :Buzz
elsif i%3==0 then puts :Fizz
else puts i
end
}

Well now.

Okay, are there any other tricks you have to show before we wrap this

up?

h=Hash.new{|d,k|k>14?h[k%15]:nil}
h[0]=:FizzBuzz
h[3]=h[6]=h[9]=h[12]=:Fizz
h[5]=h[10]=:Buzz
puts (1…100).map{|i|h[i]||i}

That looks rather familiar and similar to your first anonymous

function

solution. I think we’ve both had enough of this problem by now.

Well, it’s been nice talking to you, Mr. Martin, and I thank you for

your interest in CompuGlobalMegaTech. We’ll be in touch over the next

few days with our decision.

This is for a higher position than sheer Software Engineer, pah…

puts( %w{ Fizz Buzz FizzBuzz } * 33 + [1…100].reject{|n|
(n%3
n%5).zero? }.sort_by{ |n| exercise_is_left_to_the_reader n
}[0…99].join("\n") )

I laughed at how silly the quiz is, and then I did my solution without
fully reading the spec. :frowning:

(1…100).each do |i|
print i.to_s + ’ ’
print ‘Fizz’ if i % 3 == 0
print ‘Buzz’ if i % 5 == 0
puts
end

I missed the ‘instead of the number’ part.

Ben

On Jun 1, 2007, at 7:28 AM, Ruby Q. wrote:

Pretend you’ve just walked into a job interview and been hit with
this question. Solve it as you would under such circumstances for
this week’s Ruby Q…

This is my solution from the time when I was considering this as a quiz.

#!/usr/bin/env ruby -w

1.upto(100) do |i|
if i % 5 == 0 and i % 3 == 0
puts “FizzBuzz”
elsif i % 5 == 0
puts “Buzz”
elsif i % 3 == 0
puts “Fizz”
else
puts i
end
end

END

James Edward G. II

On 6/3/07, James Edward G. II [email protected] wrote:

This solution cracked me up, but there is a typo in it…

On Jun 3, 2007, at 9:49 AM, Fred P. wrote:

puts ‘59’
puts 'FizzBuzz
puts ‘61’

The middle line there is missing a quote. :wink:

The ‘safer’ way to do this approach might be something like:

%w{1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz
16 17 Fizz 19 Buzz Fizz 22 23 Fizz Buzz 26 Fizz 28 29
FizzBuzz
31 32 Fizz 34 Buzz Fizz 37 38 Fizz Buzz 41 Fizz 43 44 FizzBuzz
46 47 Fizz 49 Buzz Fizz 52 53 Fizz Buzz 56 Fizz 58 59 FizzBuzz
61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz 71 Fizz 73 74 FizzBuzz
76 77 Fizz 79 Buzz Fizz 82 83 Fizz Buzz 86 Fizz 88 89 FizzBuzz
91 92 Fizz 94 Buzz Fizz 97 98 Fizz Buzz
}.each {|x| puts x}

Oops now I have 11 solutions!


Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

IPMS/USA Region 12 Coordinator
http://ipmsr12.denhaven2.com/

Visit the Project Mercury Wiki Site
http://www.mercuryspacecraft.com/

quoth the Daniel M.:

Ruby Q. [email protected] writes:

Pretend you’ve just walked into a job interview and been hit with
this question. Solve it as you would under such circumstances for
this week’s Ruby Q…

Well, Mr. Martin, this is just a simple little question we ask all of

our programming candidates. Let’s see what you do with “FizzBuzz”:

<snip humourous, insightful, and bizarre solutions>

That was fantastic. Seriously, it made my morning!

-d

One-liner?

(1…100).each{|i|puts
i%3==0?(i%5==0?“FizzBuzz”:“Fizz”):(i%5==0?“Buzz”:i)}

Hi –

On Mon, 4 Jun 2007, Rick DeNatale wrote:

The ‘safer’ way to do this approach might be something like:

%w{1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz
16 17 Fizz 19 Buzz Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz
31 32 Fizz 34 Buzz Fizz 37 38 Fizz Buzz 41 Fizz 43 44 FizzBuzz
46 47 Fizz 49 Buzz Fizz 52 53 Fizz Buzz 56 Fizz 58 59 FizzBuzz
61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz 71 Fizz 73 74 FizzBuzz
76 77 Fizz 79 Buzz Fizz 82 83 Fizz Buzz 86 Fizz 88 89 FizzBuzz
91 92 Fizz 94 Buzz Fizz 97 98 Fizz Buzz
}.each {|x| puts x}

Or:

puts %w{ 1 2 Fizz 4 … }

:slight_smile:

David

#!/bin/env ruby

=begin
“Ruby Q.” [email protected] wrote in message
news:[email protected]

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

Pretend you’ve just walked into a job interview and been hit with this
question.
Solve it as you would under such circumstances for this week’s Ruby Q…

The task itself is quite boring, so I decided to imagine how
different programmers may try to pass the interview.
I hope we’ll see what the recruiter may think.

Oh! And I played golf, just for fun, hope you will enjoy it too.
=end

Q126 solution

by Sergey V.

job interview style

Java programmer

def sol1 maxn=100
for i in 1…maxn
if i%3 == 0 && i%5 == 0
puts “FizzBuzz”
elsif i%3 == 0
puts “Fizz”
elsif i%5 == 0
puts “Buzz”
else
puts i
end
end
end
puts ‘### TC1’
sol1 15

Same as above,

but the code is more manageable

def sol1a maxn=100
for i in 1…maxn
if i%3 == 0 && i%5 == 0
s = “FizzBuzz”
elsif i%3 == 0
s = “Fizz”
elsif i%5 == 0
s = “Buzz”
else
s = i.to_s
end
puts s
end
end
puts ‘### TC1a’
sol1a 15

Lisp programmer

def sol2 maxn=100
puts( (1…maxn).map{ |i|
i2s=lambda{ |n,s|
if (i%n).zero? : s else ‘’ end
}
lambda{ |s|
if s.empty? : i else s end
}.call i2s[3,‘Fizz’] + i2s[5,‘Buzz’]
} )
end
puts ‘### TC2’
sol2 15

1 year of Ruby experience

def sol3 maxn=100
1.upto(maxn){ |n|
s = “Fizz” if (n%3).zero?
(s||=‘’) << “Buzz” if (n%5).zero?
puts s||n
}
end
puts ‘### TC3’
sol3 15

Trying to get extra points for reusability…

class Fixnum
def toFizzBuzz
s = ‘Fizz’ if modulo(3).zero?
s = “#{s}Buzz” if modulo(5).zero?
s || to_s
end
end
def sol4 maxn
1.upto(maxn){ |n| puts n.toFizzBuzz }
end
puts ‘### TC4’
sol4 15

Extra points for expandability

#… who knows what else recruiters are looking for?

END

Golf style

1.upto(?d){|i|puts [“#{x=[:Fizz][i%3]}Buzz”][i%5]||x||i}# 56
1.upto(?d){|i|x=[:Fizz][i%3];puts i%5<1?“#{x}Buzz”:x||i}# 56
1.upto(?d){|i|i%3<1&&x=:Fizz;puts i%5<1?“#{x}Buzz”:x||i}# 56

Arlighty! my first submission. If I ever get asked this at a job
interview for, say, the local bookstore (i’m not exactly old enough
to get what most people call a ‘real’ job), I’ll be ready:

1.upto(?d) do |x|
p ‘fizzBuzz’ if x % 3 == 0 && x % 5
p ‘fizz’ if x % 3 == 0
p ‘buzz’ if x % 5 == 0
p x if x % 3 != 0
end

for those who wrote it in 58 chars… I don’t know what to say…
-------------------------------------------------------|
~ Ari
crap my sig won’t fit

On 6/3/07, [email protected] [email protected] wrote:

puts 'FizzBuzz
61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz 71 Fizz 73 74 FizzBuzz
76 77 Fizz 79 Buzz Fizz 82 83 Fizz Buzz 86 Fizz 88 89 FizzBuzz
91 92 Fizz 94 Buzz Fizz 97 98 Fizz Buzz
}.each {|x| puts x}

Or:

puts %w{ 1 2 Fizz 4 … }
.join(“\n”)

:slight_smile:
:-))

David

Robert

“Robert D.” [email protected] wrote in message
news:[email protected]

If I want the job :wink:

X = [ %w{FizzBuzz} + %w{Fizz} * 4 ]
Y = %w{Buzz}
(1…100).each do |n|
puts( X[n%3][n%5]) rescue puts( Y[n%5]||n )
end
Robert, you are not kind to guys who will maintain your code.
Do you want the job or demonstration of your smartness?
It’s could be great for small startup doing R&D,
but not for enterprise-like development.
imho: in any situation: KISS!

Ok, minor change to my prog - at least it will cut away 10 chars though.

1.upto(?d) do |x|
p ‘fizzBuzz’ if x % 15 == 0
p ‘fizz’ if x % 3 == 0
p ‘buzz’ if x % 5 == 0
p x if x % 3 != 0
end

--------------------------------------------|
If you’re not living on the edge,
then you’re just wasting space.

Brian C. wrote:

On Sun, Jun 03, 2007 at 11:40:51PM +0900, Joshua B. wrote:

Crud, I just tested at anarchy golf - FizzBuzz and you’re
right…

For those interested, the code was:

1.upto(?d){|i,x|i%5>0||x=:Buzz;p i%3>0?x||i:“Fizz#{x}”}
^^
Why the ,x here? x is locally scoped within the block anyway, and it
works
without it.

Yeah, I realized that shortly after posting this…still, I’m over by
2…

Oh, and just to clarify my earlier suggestion of a 56 chr random code
generator…my rough guestimate is that it would take all the computers
on the earth working together about 10^80 times the age of the universe
to find the solution…

…you know, just so all you golfers don’t feel so bad.

-Josh

On Jun 3, 2007, at 1:11 PM, Robert D. wrote:

On 6/3/07, [email protected] [email protected] wrote:

puts %w{ 1 2 Fizz 4 … }
.join(“\n”)

I think you were kidding, but just to be clear, the join() call is
not needed here.

James Edward G. II

Two quiz solutions here - one as per my interview situation, and one
for golfing.

On 6/3/07, Joshua B. [email protected] wrote:

Oh, and just to clarify my earlier suggestion of a 56 chr random code
generator…my rough guestimate is that it would take all the computers
on the earth working together about 10^80 times the age of the universe
to find the solution…

Just build a self-sustaining computer complete with time-travel
capabilities, programmed to reboot a few eons every once and a while,
and, poof there you go … an instant solution to any NP problem! I
wonder if Turing thought of such things.

On 6/3/07, S.Volkov [email protected] wrote:

“Robert D.” [email protected] wrote in message
news:[email protected]

If I want the job :wink:

X = [ %w{FizzBuzz} + %w{Fizz} * 4 ]
Y = %w{Buzz}
(1…100).each do |n|
puts( X[n%3][n%5]) rescue puts( Y[n%5]||n )
end
Robert, you are not kind to guys who will maintain your code.
That could be discussed, but this is a small entity, from my
experience maintenance nightmares come from bad design and code
dependencies. There would be some nice unit tests and if the
maintainer cannot figure out this code she can rewrite it.

Do you want the job or demonstration of your smartness?
Would I like a job that does not fit my style - unless unemployed.

This is not very smart a solution, it reflects some features of Ruby,
after all they are hiring a Ruby developer not a C or Perl developer.

It’s could be great for small startup doing R&D,
but not for enterprise-like development.
imho: in any situation: KISS!

This is strong an expression, I will not take offense, others might.

Cheers
Robert