2

Spoiler alert: I am a true novice. Tasked with figuring out fizz buzz in ruby for a class and while I have found more than a few versions of code that solve the problem, my understanding is so rudimentary that I cannot figure out how these examples truly work.

First question(refer to spoiler alert if you laugh out loud at this): How do i print out numbers one through 100 in Ruby?

Second question: can 'if else" be used to solve this? My failed code is below(attachment has screen shot):

puts('Lets play fizzbuzz')
print('enter a number: ')
number = gets()
puts(number)
if number == % 3
  puts ('fizz')
elsif number == % 5
  puts ('buzz')
elsif number == %15
  puts ('fizzbuzz')
end

Thanks,

Gumbo
  • 643,351
  • 109
  • 780
  • 844
user3290752
  • 21
  • 1
  • 1
  • 2
  • A minor point that all the answers have missed. `gets` gives you a string, which you probably want to convert to a number with `to_i`. – Max Feb 10 '14 at 00:30

12 Answers12

3

Thats ok being a novice, we all have to start somewhere right? Ruby is lovely as it get us to use blocks all the time, so to count to 100 you can use several methods on fixnum, look at the docs for more. Here is one example which might help you;

1.upto 100 do |number|
  puts number
end

For your second question maybe take a quick look at the small implementation i whipped up for you, it hopefully might help you understand this problem:

 1.upto 100 do |i|
  string = ""

  string += "Fizz" if i % 3 == 0
  string += "Buzz" if i % 5 == 0

  puts "#{i} = #{string}"

end
Oliver Atkinson
  • 7,970
  • 32
  • 43
2

First question: this problem has several solutions. For example,

10.times { |i| puts i+1 }

For true novice: https://github.com/bbatsov/ruby-style-guide

Andrew Cazares
  • 106
  • 1
  • 2
2

another method that can be helpful :

 puts (1..100).map {|i|
  f = i % 3 == 0 ? 'Fizz' : nil
  b = i % 5 == 0 ? 'Buzz' : nil
  f || b ? "#{ f }#{ b }" : i
    }
user3449311
  • 205
  • 2
  • 5
2

As a one liner

(1..100).map { |i| (i % 15).zero? ? 'FizzBuzz' : (i % 3).zero? ? 'Fizz' : (i % 5).zero? ? 'Buzz' : i  }
1

In Regards to your failed code, your conditional statements should be like this:

if number % 3 == 0
   puts "Fizz"
end
if number % 5 == 0
   puts "Buzz"
end

You don't want the last elsif statement because it will never get executed (if a number is not divisible by 3 or divisible by 5, then it is certainly not divisible by 15) Adjust for this by changing the second elsif to simply and if and if the number is divisble by 5 and not by 3, then Fizz will not be outputted but Buzz Will be

I'm just showing you how to correct your code, but as others have pointed out, there are far more elegant solutions in Ruby.

Seyon
  • 481
  • 6
  • 13
  • The problem with this is that `puts` prints a `\n` after it's printed your string so this would yield `Fizz\nBuzz` rather than `FizzBuzz` for multiples of 15. It would work fine with `print` rather than `puts` however. – sokkyoku Jun 09 '16 at 08:57
1

Not the most beautiful way to write it but good for beginners and for readability.

def fizzbuzz(n)
  (1..n).each do |i|
    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

fizzbuzz(100)
James Lieu
  • 176
  • 2
  • 6
1
1.upto(100).each do |x| # Question #1 The 'upto' method here takes is  
                        # what you would use to count in a range.               
  if (x % 3 == 0) && (x % 5 == 0)
    puts " Fizzbuzz"
  elsif x % 3 == 0
    puts " Fizz"
  elsif x % 5 == 0
    puts " Buzz"
  else
    puts x
  end
end

Question #2 Yes you can but I would look for a more elegant way to write this as a part of a definition like

def fizzbuzz(last_number)
  1.upto(last_number).each do |x|              
    if (x % 3 == 0) && (x % 5 == 0)
      puts " Fizzbuzz"
    elsif x % 3 == 0
      puts " Fizz"
    elsif x % 5 == 0
      puts " Buzz"
    else
      puts x
    end
  end
end

This is the answer that helped me to understand that no variables are being created with the .each method. Sorry about my indenting. Still learning how to use Stackoverflow text editing.

sokkyoku
  • 2,161
  • 1
  • 20
  • 22
StateOfB
  • 29
  • 1
  • 9
1

As for a more complex solution, that's one way you could build a simple DSL for quickly modifying the FizzBuzz programme (adding new divisors with their own keywords)

class FizzBuzzer
  # @return [Hash{String, Symbol => Integer}]
  attr_reader :keywords

  # @param keywords [Hash{String, Symbol => Integer}]
  def initialize(keywords)
    @keywords = keywords
  end

  # @param range [Range]
  # @return [void]
  def call(range)
    range.each do |num|
      msg = ''
      @keywords.each do |name, divisor|
        msg << name.to_s if (num % divisor).zero?
      end

      msg = num if msg.empty?
      puts msg
    end
    puts
  end
end

# create a fizz buzzer with custom keywords for divisors
CLASSIC_FIZZ_BUZZER = FizzBuzzer.new Fizz: 3, Buzz: 5
# print for a particular range
CLASSIC_FIZZ_BUZZER.call(1..25)

# you can easily define an extended fizz buzzer
EXTENDED_FIZZ_BUZZER = FizzBuzzer.new Fizz: 3, Buzz: 5, Bazz: 7, Fuzz: 11 # print 'Fuzz' when divisible by 11
EXTENDED_FIZZ_BUZZER.call(1..25)
0

Here's a quite elegant solution.

(1..100).each do |num|
  msg = ''
  msg << 'Fizz' if (num % 3).zero?
  msg << 'Buzz' if (num % 5).zero?

  msg = num if msg.empty?
  puts(msg)
end

It can be even more compact

(1..100).each do |num|
  (msg ||= '') << 'Fizz' if (num % 3).zero?
  (msg ||= '') << 'Buzz' if (num % 5).zero?
  puts msg || num
end
  • I like how compact this is but it doesn't account for FizzBuzz when the number is divisible by both 3 and 5 – Carl Apr 21 '23 at 20:36
  • Try running it and you'll see that it works properly. It's purposely written in a way that avoids an additional check. That's why I append to a string and then print it. – Mateusz Drewniak Jun 01 '23 at 08:28
-1

FizzBuzz

(1..100).each do |num|

  if num % 3 == 0 && num % 5 == 0
    puts "#{num}. FIZZBUZZ!"

  elsif num % 3 == 0
    puts "#{num}. FIZZ!"

  elsif num % 5 == 0
    puts "#{num}. BUZZ!"

  else
    puts "#{num}."
  end

end
BryanH
  • 5,826
  • 3
  • 34
  • 47
Mike
  • 1
-2

First question:

for i in 1..100
    puts i
end
tehAnswer
  • 960
  • 1
  • 13
  • 28
-2

Here is my most "idiomatic ruby" solution:

class FizzBuzz
  def perform
    iterate_to(100) do |num,out|
      out += "Fizz" if num.divisable_by?(3)
      out += "Buzz" if num.divisable_by?(5)
      out || num
    end
  end

  def iterate_to(max)
    (1..max).each do |num|
      puts yield num,nil
    end
  end
end

class Fixnum
  def divisable_by?(num)
    self % num == 0
  end
end

class NilClass
  def +(other)
    other
  end
end

FizzBuzz.new.perform

And it works:

https://gist.github.com/galori/47db94ecb822de2ac17c

Gal
  • 5,537
  • 1
  • 22
  • 20