Bad value for range - ruby

When I run the following code:
def db(y)
return self % y == 0
end
puts "To number:"
n = gets.chomp
for i in 1..n
if i.db(3)
puts "Fizz!"
if i.db(5)
puts "FIZZBUZZ!"
end
elsif i.db(5)
puts "Buzz!"
else
puts i
end
end
I get a "bad value for range" error. Why does this happen how do I fix it? Normal ranges that use variables for some values work perfectly including for loops, why does this not work?
Note: I want the for loop to stay as a for loop.

Just do as below :
n = gets.chomp.to_i
gets.chomp will give you String instance. You need to make it as Fixnum. Otherwise 1.."4" for e.g is not a valid range. so error "bad value for range" error. String#to_i is your friend.
2.0.0p0 :001 > 1.."2"
ArgumentError: bad value for range
from (irb):1
from /home/kirti/.rvm/rubies/ruby-2.0.0-p0/bin/irb:16:in `<main>'
2.0.0p0 :002 > 1..2
=> 1..2
2.0.0p0 :003 >

gets returns String.
You need to convert it to Fixnum using String#to_i.
Replace the following line:
n = gets.chomp
With:
n = gets.chomp.to_i

Related

Write a program which gets a number from a user and identify whether it is an Integer or a Float in ruby

I am trying this :
print " Enter Value "
num = gets.chomp
also tried .kind_of? but didn't work
if num.is_a? Float
print " Number is in float "
also tried .kind_of? but didn't work
else num.is_a? Integer
print " Number is in integer "
end
Your problem here is that gets returns a String you can actually determine this based on the fact that you are chaining String#chomp, which removes the trailing "separator" which by default is return characters (newlines) e.g.
num = gets.chomp # User enters 1
#=> "1"
In order to turn this String into a Numeric you could explicitly cast it via to_i or to_f however you are trying to determine which one it is.
Given this requirement I would recommend the usage of Kernel#Integer and Kernel#Float as these methods are strict about how they handle this conversion. knowing this we can change your code to
print " Enter Value "
num = gets.chomp
if Integer(num, exception: false)
puts "#{num} is an Integer"
elsif Float(num, exception: false)
puts "#{num} is a Float"
else
puts "#{num} is neither an Integer or a Float"
end
Note: the use of exception: false causes these methods to return nil if the String cannot be converted to the desired object, without it both methods will raise an ArgumentError. Additionally when I say these methods are strict about conversion a simple example would be Integer("1.0") #=> ArgumentError because while 1 == 1.0, 1.0 itself is a Float and thus not an Integer
Some examples:
num = 6.6
num.is_a?(Integer)
=> false
num.is_a?(Float)
=> true
num = 6
num.is_a?(Integer)
=> true
num.is_a?(Float)
=> false
Minor note, #print is not the correct method to print to the screen. The correct method is #puts.
So your code would look like this:
if num.is_a?(Float)
puts 'Number is a float.'
elsif num.is_a?(Integer)
puts 'Number is an integer.'
else
puts 'Number is neither a float nor an integer.'
end
I suspect #gets returns a string though, which means you'll need to convert from a string into a numeric first.

Ruby Error: wrong number of arguments (given 4, expected 0) (ArgumentError)

I am a ruby beginner and I am trying to make a method called print that prints all the elements in a given array. I want my code to get an undefined local variable error.
This is what I got from Youtube. This gives an undefined local variable error.
movies = ["good","bad"]
def good_movies
movies.each do |movies|
puts "I like #{movie}"
end
end
good_movies
I am using interactive Ruby. This is my version.
numbers = [1,2,3]
def print
numbers.each do |number|
puts "#{number}"
end
end
print
I am getting an error: (irb):2:in `print': wrong number of arguments (given 4, expected 0) (ArgumentError). Why am I getting this, not the undefined local variable error?
What is going on?
You have to pass an argument 'numbers" to the print method.
numbers = [1,2,3]
def print(nums)
nums.each do |number|
puts number
end
end
And then:
print(numbers)

Ruby, random number generator and if statement

After running this program, it only ever returns "miss"
What have I done wrong?
def method
print "Enter number from 0 to 4"
x = gets.chomp
num = rand(5)
if x == num
puts "hit"
else
puts "miss"
end
end
while 1==1
method
end
thanks
gets.chomp results in a String. Comparing a String to a number with equality will never be true, because they are completely different types.
You should convert x to an integer before comparison, using String#to_i:
x = gets.chomp.to_i
Also, while 1==1 is a bit strange. This is more readable:
while true
method
end
Or even better:
loop { method }
You are reading a string from $stdin:
Change
x = gets.chomp
to
x = gets.chomp.to_i
Hope this helps
Reference
String#to_i

using assert_raise within ruby testing

I'm creating a testing file for a ruby program that finds factorials of given numbers. All of my tests run well except I get an error with my string and negative number tests that should raise exceptions. I'm not entirely sure of the syntax for raise exception, I've read the docs.
this is my code for the factorial program itself, n is the number thats supposed to be passed:
if n.is_a?(Integer) == false
raise 'strings are not acceptable'
end
if n < 0
raise 'negatives are not acceptable'
end
the test case in my test file are as follows:
def test_negative
factorial(-1)
assert_raise do
end
end
def test_string
factorial('hello')
assert_raise do
end
end
both of my tests come back as errors while my other 3, that test normal numbers, come back as passed. I'm new to ruby but I would just want a pass after assert_raise do as my actual error message is in my factorial program right?
in your first test case, it will not return an error because -1 is also considered as an Integer
#irb output
2.0.0-p247 :003 > a = -1
=> -1
2.0.0-p247 :004 > a.is_a?(Integer)
=> true
and in your second case, when you pass a string, it will error even before going inside your condition as you are trying to compare string with an integer
#irb outout
2.0.0-p247 :007 > "hello" < 0
ArgumentError: comparison of String with 0 failed
from (irb):7:in `<'
from (irb):7
and off topic, you could write
if n.is_a?(Integer) == false
raise 'strings are not acceptable'
end
as (more ruby way :))
raise 'strings are not acceptable' unless n.is_a?(Integer)

Mysterious error with beginner's ruby code (while loops)

So this is my code. I'm learning while loops and not sure why this doesn't work. I'm getting an error.
i = 0
numbers = []
def while_var(x)
while i < #{x}
print "Entry #{i}: i is now #{i}."
numbers.push(i)
puts "The numbers array is now #{numbers}."
i = i + 1
puts "variable i just increased by 1. It is now #{i}."
end
while_var(6)
puts "Want to see all the entries of the numbers array individually (i.e. not in array format)? Here you go!"
for num in numbers
puts num
end
puts "1337"
This is my error
1.rb:5: syntax error, unexpected tSTRING_BEG, expecting keyword_do or '{' or '('
print "Entry #{i}: i is now #{i}."
^
I have no idea what this is all about. Thanks.
EDIT
So I have this revised code
def while_var(x)
i = 0
numbers = []
while i < x
print "Entry #{i}: i is now #{i}."
numbers.push(i)
puts "The numbers array is now #{numbers}."
i = i + 1
puts "variable i just increased by 1. It is now #{i}."
end
puts "next part"
for num in numbers
puts num
end
end
while_var(6)
It works when I type it line-by-line into irb, but not when I run the file with ruby. What gives? I'm getting this error:
Entry 0: i is now 0.1.rb:8:in `while_var': undefined method `push' for nil:NilClass (NoMethodError)
from 1.rb:23:in `<main>'
EDIT : Figured it out. All I had to do was change the "print" to "puts" for some reason.
Here is the fixed code :
def while_var(x)
i = 0
numbers = []
while i < x
print "Entry #{i}: i is now #{i}."
numbers.push(i)
puts "The numbers array is now #{numbers}."
i = i + 1
puts "variable i just increased by 1. It is now #{i}."
end
end
You did several mistakes :
You forgot to close the while loop.
You used #{x} which is not correct syntax for interpolation,But you don't need interpolation here. make it only x.
Inside the method two local variables i and numbers can't be used,as they have created at the top level. So you need to create those variables locally inside the method.
This code should work:
def while_var(x)
i = 0
numbers = []
while i < x
puts "Entry #{i}: i is now #{i}."
numbers.push(i)
puts "The numbers array is now #{numbers}."
i = i + 1
puts "variable i just increased by 1. It is now #{i}."
end
numbers
end
numbers = while_var(6)
puts "Want to see all the entries of the numbers array individually (i.e. not in array format)? Here you go!"
for num in numbers
puts num
end
I hope it does what you wanted to achieve.
You should use puts to print something to console. And move i and numbers variables to while_var method.

Resources