String can't be coerced into Fixnum Ruby - ruby

I'm trying to learn ruby, and was tasked with creating a simple program that grabs user input, and then uses an elsif statement to give a possible 3 different answers. Here's my code:
print "What is your birth year?"
year = gets.chomp
age = 2016 - year
if age >= 40
puts "You're old!"
elsif age.between?(25, 39)
puts "You aren't too old!"
else
puts "You're just a baby!"
end
However, I keep getting "String can't be coerced into Fixnum"
I don't recall in the lessons doing something like I'm doing for the "age" variable, so I could be doing it wrong, but I also couldn't find an answer in my lessons or online. Any help would be greatly appreciated!

Remember that gets returns a string value, and in Ruby strings and numeric values are completely different things. Some other languages will coerce them as necessary, like PHP, Perl or JavaScript, but Ruby does not.
To make this work:
year = gets.chomp.to_i
Although technically to_i alone is usually sufficient.

Related

I'm trying to convert a value to an integer what am I doing wrong here?

I'm just trying to make this code work and I keep getting:
<=': comparison of String with 21 failed (ArgumentError)
Please tell me what I'm doing wrong.
I'm learning and I've gone through every iteration of the code I can think of to try and make it work, I'm just not sure what I've done wrong.
puts "How old are you?"
old = gets.chomp
if old <= 21
return "You are not legally allowed to buy alcohol in the US"
else
return "You are legally allowed to buy alcohol in the US"
end
I believe you have to use to_i to convert the string into an integer.
The previous answer is correct but more verbosely, here is the line you need to change in your code:
old = gets.chomp.to_i
But you might also want to make sure user only enters an integer because calling .to_i on non-numeric characters will return 0.
You might want to look at Accept only numeric input
Try/improve as needed:
input = gets.chomp
if(val = Integer(input) rescue false)
val < 21 ? 'Not old enough' : 'The usual martini?'
else
'You did not provide an age (number)'
end
It checks if the input is an Integer, so it accounts for an input like foo.
Hth...

unique rand number in a ruby loop

I am reading the book "Learn to program", and I have come across an exercise that I am having trouble with.
year = (rand(1900...1990))
while true do
puts "What would you like to say to grandma?"
ask = gets.chomp
if
ask == ask.downcase
puts "SPEAK UP SONNY"
elsif
ask == ask.upcase
puts "NO, NOT SINCE #{year}!"
end
break if ask == "BYE"
end
everything is functioning properly, but if the rand number "year" comes up more than once, it repeats the same number. Is there a way to have it become a unique random number each time it comes up during the same loop?
thank you in advance
Move year assignment into the loop to have it assigned before each chomp.
The value of year does not change within the loop because it is defined outside the loop. It would change if the definition were moved inside the loop, but you still may have years repeated. To fix both of these problems, change
year = rand(1900...1990)
to
years = (1900...1990).to_a.shuffle
(outside the loop) and change
puts "NO, NOT SINCE #{year}!"
to
puts "NO, NOT SINCE #{years.shift}!"
(or years.pop). If this is repeated more than 91 times an exception will be raised.

Ruby until always validates as false?

So I've written this piece of code to play around with numbers and the until loop:
number = rand(10)
puts number
puts "Guess the number"
guess = gets.chomp
until guess == number
puts "Guess again!"
guess = gets.chomp
end
puts "You've guessed it right! The number is #{guess}
But for some reason it it always stuck in the until loop and I am not sure why. I puts the random number to know that i guess right and try out the code. I'm completely new to Ruby, So I guess it's a very obvious thing I am missing, but I just dont see it.
From my point of view, whenever I prompt for the guess again, that guess that validated by the until loop with until guess == number.
Who can help me clear this up?
The reason is simple, and that is you're failing to cast the user input into an integer.
i.e. if I write
number = gets.chomp
and I type 1 for the number, then the number variable will equal the string "1", not the integer 1.
To fix this, just use guess = gets.chomp.to_i
Instead of guess = gets.chomp(which will return a string of the user input), use guess = gets.to_i (which will convert user input into integer)
to_i method will convert the element into integer and will drop /n character since it's not part of the integer. Don't need to add .chomp method.

trying to use each method to find divisible numbers and print them

I'm new to ruby and new to stack. I am trying to use the .each method on an array of numbers to see which numbers are divisible by 4, and 400. It is based on an exercises from Chris Pine's "Learn to Program" Ruby tutorial. In it you are supposed to find the leap years, then print them, from a range of years that the user inputs. I accomplished this using an if/else statement...but it seems to me this should be able to be done using the each method, or maybe the map method? Less code.
For example:
puts "Enter two years (to - from) to find out which years are leap years!"
puts "Enter the first year.."
year1 = gets.chomp.to_i
puts "Now enter the second year"
year2 = gets.chomp.to_i
range = (year1..year2).to_a
puts "These are the leap years between those years:"
range.each do |year|
leaps = (year % 4 == 0 || year % 400 == 0)
end
puts leaps
this code may not be correct, but i have toyed with different ways of doing it (puts inside .each, defining variable outside, etc...) but nothing seems to work. Like I said, I accomplished it with an if/else...I just feel there may be a better way, and it's driving me nuts. Do i not understand the .each correctly? am i using the wrong method? can it be done at all using each/map/or collect???? Thanks in advance!
You need to puts inside the each block too. Also, you can just divide by 4 and check if the remainder is 0. No need of 400
range.each do |year|
puts year if year % 4 == 0;
end
The puts year will be executed only if the if condition is satisfied.

Multiplying variables in Ruby?

I'm trying to create a simple pay predictor program.
I am capturing two variables, then want to multiply those variables. I have tried doing
pay = payrate * hourrate
but it seems not to work. I was told to put pay in a definition, then I tried to display the variable but it still didn't work. When I looked at the documentation, it seems that I am using the correct operator. Any guesses?
# Simple Budgeting Program
puts "What is your budget type?\nYou can say 'Monthly' 'Weekly' or 'Fortnightly'"
payperiod = gets.chomp
case payperiod
when "Monthly"
puts "You are paid monthly"
when "Weekly"
puts "You are paid weekly"
when "Fortnightly"
puts "You are paid every two weeks."
else
puts "You did not input a correct answer."
end
puts "What is your hourly rate?\n"
payrate = gets.chomp
puts "How many hours have you worked during your pay period?\n"
hourrate = gets.chomp
def pay
payrate * hourrate
end
puts "#{pay}"
preventclose = gets.chomp
The def has nothing to do with it. payrate and hourrate are strings and * means a very different thing to strings. You need to convert them to numbers first with to_i or to_f.
payrate.to_f * hourrate.to_f
You declared pay rate and hour rate as strings. In Ruby, you cannot multiply strings by other strings. However, in Ruby there are type conversions. Ruby's string class offers a method of converting strings to integers.
string = "4"
string.to_i => 4
In your case, you first need to convert BOTH strings to an integer.
def pay
payrate.to_i * hourrate.to_i
end
Here's some great information about strings.
http://www.ruby-doc.org/core-2.1.2/String.html
Hope this helps
Coercing Strings into Numbers, and Back Again
Kernel#gets generally returns a string, not an integer or floating point number. In order to perform numeric calculations, you need to coerce the string into a number first. There are a number of ways to do this, but the Kernel#Float method is often safer than String#to_i because the Kernel method will raise an exception if a string can't be coerced. For example:
print 'Pay Rate: '
rate = Float(gets.chomp)
print 'Hours Worked: '
print hours = Float(gets.chomp)
Of course, operations on floating point numbers can be inaccurate, so you might want to consider using Kernel#Rational and then converting to floating point for your output. For example, consider:
# Return a float with two decimal places as a string.
def pay rate, hours
sprintf '%.2f', Rational(rate) * Rational(hours)
end
p pay 10, 39.33
"393.30"
#=> "393.30"

Resources