Ruby Quiz <james / grayproductions.net> 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 Quiz.

# 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'.split*99,'////Buzz'.split*99) {|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.


-- 
s=%q(  Daniel Martin -- martin / snowplow.org
       puts "s=%q(#{s})",s.to_a.last       )
       puts "s=%q(#{s})",s.to_a.last