A little late on the fizz buzz problem

August 27, 2010 § 9 Comments

[tweetmeme service=’bit.ly’]

My two cents in Ruby.  Extending the Fixnum class allows you to call .to_fizz_buzz_string instead of .to_s if you want the fizz buzz version of an integer rather than the usual string version.

#!/usr/bin/ruby

class Fixnum
  def Fixnum.fizz_buzz_entities
    {
      3 => 'Fizz',
      5 => 'Buzz',
    }
  end

  def to_fizz_buzz_string
    fb = Fixnum::fizz_buzz_entities.inject('') { |result, kv| result << kv[1] if (self % kv[0]).zero?; result }
    fb.empty? ? self.to_s : fb
  end
end

(1..100).each { |i| puts i.to_fizz_buzz_string }

Inspired by The Fizz Buzz problem and diving in too soon and The Fizz Buzz Problem.

Tagged: ,

§ 9 Responses to A little late on the fizz buzz problem

  • Anonymous says:

    Twitter Trackbacks…

  • B says:

    It seems that it prints BuzzFizz for 15, while it should be FizzBuzz? (ruby 1.8.7)

    • fringley says:

      Yes, this is a problem with using a hash to contain the entities. As the hash order is indeterminate, then it is possible to get BuzzFizz as well as FizzBuzz depending on how .each enumerates the hash contents. If the order was important, then a different data structure would need to be used, probably an array.

  • fringley says:

    To print out the representations in a deterministic order, use an array instead of a hash. Also, a space between Fizz and Buzz might be more readable:

    class Fixnum
      def Fixnum.fizz_buzz_entities
        [
          {:integer => 3, :representation => 'Fizz'},
          {:integer => 5, :representation => 'Buzz'},
        ]
      end
    
      def to_fizz_buzz_string
        fb = Fixnum::fizz_buzz_entities.inject([]) { |result, kv| result << kv[:representation] if (self % kv[:integer]).zero?; result }
        fb.empty? ? self.to_s : fb.join(' ')
      end
    end
    
  • Pat Parslow says:

    I’m a big fan of this solution:

    def fizzbuzz_rand_sequence15_3201
      (0..99).map {|i| srand(46308667) if (i%15).zero?; ["FizzBuzz", "Buzz", i+1, "Fizz"][rand(4)]}
    end
    

    from the fizzbuzz gem at http://fizzbuzz.rubyforge.org/svn/trunk/lib/fizzbuzz.rb

    • fringley says:

      Haha! Ok, yes that is pretty clever, took me a little while to understand what was going on there – at first look I thought it was going to be completely random :)

      I think one of the original requirements was easy understanding and extensibility – not sure how well this solution would score on them!!

  • Pat Parslow says:

    How about getting rid of that return variable you are using:

    def to_fizz_buzz_string
        Fixnum::fizz_buzz_entities.inject([self.to_s]) { |result, kv| 
         (self % kv[:integer]).zero? ? result << kv[:representation] : result 
         }.join(' ').gsub("#{self.to_s} ",'')
    end
    

    I couldn’t think of how to test on the result of the inject and return it if appropriate; I’m sure there should be a way. But sticking the number in and removing it again later if necessary works… ;-)

    • fringley says:

      Yes, I had the same problem – I couldn’t think of a neat way either. The gsub is a pretty succinct solution though :)

      • Pat Parslow says:

        Just thinking about that, it is something I want to do quite often – return the object itself if it meets some criterion, or something else if it doesn’t. My not-very-flexible solution to that is

        class Object
         def mytest?(condition,param,elsedo)
          self.send(condition,param)? self : elsedo
         end
        end
        
        3.mytest?(:>,5,'woof')

        I’m sure that could be made rather nicer, allowing elsedo to be a block, for instance (and, indeed, the comparison to be a block…)

Leave a reply to Anonymous Cancel reply

What’s this?

You are currently reading A little late on the fizz buzz problem at Fringley's Blog.

meta