Why isn't this working. I am attempting to refactor the code to use the smallest number of characters possible..
for i in 1..200 # 33
if (i%3 == 0) # 34
if (i%5 == 0) ? puts "FizzBuzz" : puts 'Fizz' # 35
end # 36
elsif (i%5 == 0) ? puts "FizzBuzz" # 37
if (i%3 == 0) # 38
else puts "Buzz" # 39
end # 40
else puts i # 41
end # 42
end # 43
If you want to use nested if-else you can use
(1..200).each do |num|
if (num%3 == 0 && num%5 == 0)
puts "BucksFizz"
elsif num%3 == 0
puts "Bucks"
elsif num%5 == 0
puts "Fizz"
elsif
puts num
end
end
use puts i%5 == 0 ? "FizzBuzz" :'Fizz'
instead of if (i%5 == 0) ? puts "FizzBuzz" : puts 'Fizz'
Do this for all such statements
Related
I have written the logic for the program to perform FizzBuzz operations:
fizzbuzz
module FizzBuzz
class Operation
def input
puts 'Enter a number upto which Fizz/Buzz needs to be printed'
num = gets.chomp.to_i
fizzbuzz_function(num)
end
def fizzbuzz_function(num)
for i in 1..num
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
end
res = Operation.new
res.input
end
But I am trying to print the output in form of a table.
Here is FizzBuzz in form of a table:
def fizzbuzz_gen(num)
Enumerator.new do |y|
(1..num).each do |i|
if i % 3 == 0 && i % 5 == 0
y << 'FizzBuzz'
elsif i % 3 == 0
y << 'Fizz'
elsif i % 5 == 0
y << 'Buzz'
else
y << i.to_s
end
end
end
end
def fill_to_width(width, e)
result = ""
future_length = -1
while result.length + future_length < width
result << e.next
result << " "
future_length = e.peek.length
end
result.center(width)
end
def format_table(num)
fb = fizzbuzz_gen(num)
begin
puts fill_to_width(75, fb)
puts fill_to_width(75, fb)
loop do
puts "%10s%s%31s%s" % ["", fill_to_width(12, fb), "", fill_to_width(12, fb)]
end
rescue StopIteration
end
end
format_table(100)
There may be less numbers output than specified, in order for one leg not to be shorter than another.
I'm trying to write a looping fizzbuzz code that ends with the user_input's number. So far the code works, but it loops the number of times you put in for the user_input, not end at the user_input's limit. For example, if I type in 25, it will loop 25 times, and not end at 25. How do I set the parameters/range?
Here is my code:
puts("Please select a number that is at least 25. This is the limit for the fizzbuzz game.")
user_input = gets().chomp().to_i
if
user_input < 25
puts("Please select a larger number.")
else
user_input >= 25
user_input = user_input
counter = 1
while counter < user_input
puts(counter)
counter = counter + 1
(1..user_input).step 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
end
It is optional to write () when you send no parameters to a method and usually discouraged
You shouldn't use else user_input >= 25, else is enough
user_input = user_input is totally useless line
while cycles with counters isn't the way rubists code, prefer iterators. Moreover, you shouldn't have while here at all
puts 'Please select a number that is at least 25. This is the limit for the fizzbuzz game.'
user_input = gets.chomp.to_i
if user_input < 25
puts 'Please select a larger number.'
else
1.upto(user_input) 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
optionally, you can use case-when instead of multiple elsif statements:
puts 'Please select a number that is at least 25. This is the limit for the fizzbuzz game.'
user_input = gets.chomp.to_i
if user_input < 25
puts 'Please select a larger number.'
else
1.upto(user_input) do |i|
case
when [3, 5].all? { |n| i % n == 0 }; puts 'fizzbuzz'
when i % 3 == 0; puts 'fizz'
when i % 5 == 0; puts 'buzz'
else; puts i
end
end
end
I have this if statement:
if value_n_in_f > 0 && value_m_in_f != 1
puts "I: f(x)=#{value_m_in_f}x+#{value_n_in_f}"
elsif value_n_in_f == 0 && value_m_in_f != 1
puts "I: f(x)=#{value_m_in_f}x"
elsif value_n_in_f < 0 && value_m_in_f != 1
puts "I: f(x)=#{value_m_in_f}x#{value_n_in_f}"
elsif value_n_in_f > 0 && value_m_in_f == 1
puts "I: f(x)=x+#{value_n_in_f}"
elsif value_n_in_f == 0 && value_m_in_f == 1
puts "I: f(x)=x"
elsif value_n_in_f < 0 && value_m_in_f == 1
puts "I: f(x)=x#{value_n_in_f}"
end`
I have to use this statement really often in other statements and it makes my code unnecessarily long. Obviously if_for_f=if ....... end won't work. Is there any other way?
Here's an example what I want it to look like:
puts "Now we insert #{value_of_x} in #{if_for_f}"
Is there any way I can do something like this? Note that I am absolutly new to this.
Thanks in advance,
Kaiton
can't I just def a function with its function to run this case
statement and call it then when I need it it?
Of course:
def do_stuff(m, n)
if m == 1
if n > 0 then "I: f(x)=x+#{n}"
elsif n == 0 then "I: f(x)=x"
elsif n < 0 then "I: f(x)=x#{n}"
end
else
if n > 0 then "I: f(x)=#{m}x+#{n}"
elsif n == 0 then "I: f(x)=#{m}x"
elsif n < 0 then "I: f(x)=#{m}x#{n}"
end
end
end
puts do_stuff(1, 1) #I: f(x)=x+1
Or, if compactness is the goal, we can get to this:
def do_stuff(m, n)
if m == 1
n == 0 ? "I: f(x)=x" : "I: f(x)=x#{sprintf("%+d", n)}"
else
n == 0 ? "I: f(x)=#{m}x" : "I: f(x)=#{m}x#{sprintf("%+d", n)}"
end
end
...and then a one liner:
def do_stuff(m, n)
(m == 1) ? (n == 0 ? "I: f(x)=x" : "I: f(x)=x#{sprintf("%+d", n)}") : (n == 0 ? "I: f(x)=#{m}x" : "I: f(x)=#{m}x#{sprintf("%+d", n)}")
end
end
But your methodology has some problems with zeros and -1:
def do_stuff(value_m_in_f, value_n_in_f)
if value_n_in_f > 0 && value_m_in_f != 1
puts "I: f(x)=#{value_m_in_f}x+#{value_n_in_f}"
elsif value_n_in_f == 0 && value_m_in_f != 1
puts "I: f(x)=#{value_m_in_f}x"
elsif value_n_in_f < 0 && value_m_in_f != 1
puts "I: f(x)=#{value_m_in_f}x#{value_n_in_f}"
elsif value_n_in_f > 0 && value_m_in_f == 1
puts "I: f(x)=x+#{value_n_in_f}"
elsif value_n_in_f == 0 && value_m_in_f == 1
puts "I: f(x)=x"
elsif value_n_in_f < 0 && value_m_in_f == 1
puts "I: f(x)=x#{value_n_in_f}"
end
end
do_stuff(1, 0)
do_stuff(1,-1)
do_stuff(1, 1)
do_stuff(0,-1)
do_stuff(0, 0)
do_stuff(-1, 1)
--output:--
I: f(x)=x
I: f(x)=x-1
I: f(x)=x+1
I: f(x)=0x-1 #<---HERE
I: f(x)=0x #<---HERE
I: f(x)=-1x+1 #<---HERE
So let's fix that:
def get_line_equ(m, b)
constant = (b == 0) ? "" : sprintf("%+d", b) # 2 => "+2"
case m
when 0
xterm = ""
constant = b
when 1
xterm = "x"
when -1
xterm = "-x"
else
xterm = "#{m}x"
end
"I: f(x)=#{xterm}#{constant}"
end
puts get_line_equ(0, 0)
puts get_line_equ(0, -1)
puts get_line_equ(0, 1)
puts get_line_equ(1, 0)
puts get_line_equ(1,-1)
puts get_line_equ(1, 1)
puts get_line_equ(-1, 0)
puts get_line_equ(-1, -1)
puts get_line_equ(-1, 1)
puts get_line_equ(2, 0)
puts get_line_equ(2, -1)
puts get_line_equ(2, 1)
--output:--
I: f(x)=0
I: f(x)=-1
I: f(x)=1
I: f(x)=x
I: f(x)=x-1
I: f(x)=x+1
I: f(x)=-x
I: f(x)=-x-1
I: f(x)=-x+1
I: f(x)=2x
I: f(x)=2x-1
I: f(x)=2x+1
Better?
spoiler:
The final def is not as efficient as it could be: the first line should be removed and copied to each of the when branches--except for the first.
In response to comment:
def my_sprintf(str, *numbers)
str.gsub(/% .*? [df]/x) do |match| #Looks for %...d or %...f sequences
puts match
end
end
my_sprintf("The answer is: %+d or %+d", -2, 3)
--output:--
%+d
%+d
Next:
def my_sprintf(str, *numbers)
str.gsub(/% .*? [df]/x) do |format_sequ|
number_as_str = numbers.shift.to_s
p number_as_str
if format_sequ[1] == "+" and number_as_str[0] != "-"
"+#{number_as_str}"
else
number_as_str
end
end
end
puts my_sprintf("The answer is: %+d or %+d.", -2, 3)
--output:--
"-2"
"3"
The answer is: -2 or +3.
Here's a more compact way to write your case statement. Recall that a <=> b => -1 if a < b, a <=> b => 0 if a == b and a <=> b => -1 if a > b.
"I: f(x)=" +
case [value_n_in_f <=> 0, value_m_in_f == 1]
when [ 1,false] then "#{value_m_in_f}x+#{value_n_in_f}"
when [ 0,false] then "#{value_m_in_f}x"
when [-1,false] then "#{value_m_in_f}x#{value_n_in_f}"
when [ 1,true] then "x+#{value_n_in_f}"
when [ 0,true] then "x"
when [-1,true] then "x#{value_n_in_f}"
end
If you wish to demonstrate how the string is built, you could do something like this (with value_n_in_f and value_m_in_f renamed intercept and slope, respectively):
"I: f(x)=" +
case
when slope.zero?
intercept.zero? ? "0" : "#{intercept}"
else
case slope.to_f
when 1.0 then ""
when -1.0 then "-"
else "#{slope}"
end + "x" +
case intercept <=> 0
when 0 then ""
when -1 then "#{intercept}"
else "+#{intercept}"
end
end
Note that this permits slope < 0, which is not part of the specification. I tested this for various combinations of intercept and slope:
intercept slope string
-2.1 4 I: f(x)=4x-2.1
-2.1 -2.2 I: f(x)=-2.2x-2.1
-2.1 0 I: f(x)=-2.1
-2.1 0.0 I: f(x)=-2.1
-2.1 -1 I: f(x)=-x-2.1
-2.1 1.0 I: f(x)=x-2.1
0 4 I: f(x)=4x
0 -2.2 I: f(x)=-2.2x
0 0 I: f(x)=0
0 0.0 I: f(x)=0
0 -1 I: f(x)=-x
0 1.0 I: f(x)=x
0.0 4 I: f(x)=4x
0.0 -2.2 I: f(x)=-2.2x
0.0 0 I: f(x)=0
0.0 0.0 I: f(x)=0
0.0 -1 I: f(x)=-x
0.0 1.0 I: f(x)=x
3 4 I: f(x)=4x+3
3 -2.2 I: f(x)=-2.2x+3
3 0 I: f(x)=3
3 0.0 I: f(x)=3
3 -1 I: f(x)=-x+3
3 1.0 I: f(x)=x+3
A couple of things here: you can put "puts" before the whole if/elsif block and avoid having puts on every line, like so:
puts case
when (value_n_in_f > 0 && value_m_in_f != 1) then "I: f(x)=#{value_m_in_f}x+#{value_n_in_f}"
when (value_n_in_f == 0 && value_m_in_f != 1) then "I: f(x)=#{value_m_in_f}x"
end
Second, a case statement would be much more readable, like so:
def big_compare(value_n_in_f, value_m_in_f)
msg = case
when (value_n_in_f > 0 && value_m_in_f != 1) then "I: f(x)=#{value_m_in_f}x+#{value_n_in_f}"
when (value_n_in_f == 0 && value_m_in_f != 1) then "I: f(x)=#{value_m_in_f}x"
when (value_n_in_f < 0 && value_m_in_f != 1) then "I: f(x)=#{value_m_in_f}x#{value_n_in_f}"
when (value_n_in_f > 0 && value_m_in_f == 1) then "I: f(x)=x+#{value_n_in_f}"
when (value_n_in_f == 0 && value_m_in_f == 1) then "I: f(x)=x"
when (value_n_in_f < 0 && value_m_in_f == 1) then "I: f(x)=x#{value_n_in_f}"
end
end
puts big_compare(0, 0)
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,
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
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
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
}
As a one liner
(1..100).map { |i| (i % 15).zero? ? 'FizzBuzz' : (i % 3).zero? ? 'Fizz' : (i % 5).zero? ? 'Buzz' : i }
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.
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)
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.
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)
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
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
First question:
for i in 1..100
puts i
end
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
I have an if/else condition, and the if and else sections are identical, save for the operator used. In one case <, and in the other >. Is there a way to conditionally set that operator, to DRY out the code?
if count_year < end_year
while count_year <= end_year
if count_year % 4 == 0
if count_year % 100 != 0
all_years << count_year unless (count_year % 400 == 0)
end
end
count_year += 1
end
puts all_years
elsif count_year > end_year
while count_year >= end_year
if count_year % 4 == 0
if count_year % 100 != 0
all_years << count_year unless (count_year % 400 == 0)
end
end
count_year -= 1
end
puts all_years.reverse
end
This is part of a program for printing out leap years between two given years. I feel like there must be a way to not have to repeat the loop twice. Something like: count_year < end_year ? operator = "<" : operator = ">" - Then using that variable to substitute the operator into a code block or something? Any ideas?
For one small improvement, you can extract really identical parts into a method. Then duplication stops being so massive.
# I'm too lazy to come up with a proper name for it.
def foo count_year, all_years
if count_year % 4 == 0
if count_year % 100 != 0
all_years << count_year unless (count_year % 400 == 0)
end
end
end
# later...
if count_year < end_year
while count_year <= end_year
foo count_year, all_years
count_year += 1
end
puts all_years
elsif count_year > end_year
while count_year >= end_year
foo count_year, all_years
count_year -= 1
end
puts all_years.reverse
end
But, the operator substitution...
Yes, there is a way to dynamically choose an operator for evaluation. You see, operators in ruby are just method calls, nothing more. These two lines are equivalent:
7 > 5
7.>(5)
And here's a snippet that chooses random operator for comparison. I leave it up to you to adapt it for your problem (if you want, that is. I advise you against this).
def is_7_greater_than_5
operator = [:<, :>].sample # pick random operator
7.send(operator, 5)
end
is_7_greater_than_5 # => false
is_7_greater_than_5 # => false
is_7_greater_than_5 # => true
is_7_greater_than_5 # => true
is_7_greater_than_5 # => true
def example count_year, end_year
all_years = []
dir, test = count_year < end_year ?
[ 1, proc { |c, e| c <= e }] : count_year > end_year ?
[-1, proc { |c, e| c > e }] :
[ 0, proc { |c, e| false }]
while test.call count_year, end_year
if count_year % 4 == 0
if count_year % 100 != 0
all_years << count_year unless count_year % 400 == 0
end
end
count_year += dir
puts dir > 0 ? all_years : all_years.reverse
end
end
Aww. Why did you do a code golf exercise and accept an answer so quickly? Boo! :( hehe. just kidding. The early bird gets the worm. I perhaps took the problem too literally as I think you're just looking to experiment with compare.
I would use the built in functions of ruby and decomposed this method into a class. :)
require 'date'
class LeapYearFinder
attr_reader :years, :years_reversed
def initialize(start_year, end_year)
#start_year = Date.parse("1/1/#{start_year.to_s}")
#end_year = Date.parse("1/1/#{end_year.to_s}")
#years ||= leap_years
end
def compare_range
#compare_range ||= Range.new(#start_year, #end_year)
end
def leap_years
years = []
compare_range.step {|x| years << x.year if x.leap? }
years.uniq!
end
def years_reversed
#years.reverse
end
end
lp = LeapYearFinder.new(1900, 2012)
puts "Years putzed"
lp.years.map {|x| puts x}
puts "Years reversed"
lp.years_reversed.map {|x| puts x}
Some corner case issues
handle a reverse date input
step properly through the range thus avoiding the uniq! and maybe yielding better performance