How to compare a sum of expressions with integer in Ruby? - ruby

I am learning Ruby and faced with some problem.I tried to compare a sum of expressions with integer and get this return: "comparison of String with 2000 failed". Thanks a lot!
puts "Hello! Please type here your birthday date."
puts "Day"
day = gets.chomp
day.capitalize!
puts "Month"
month = gets.chomp
month.capitalize!
puts "Year"
year = gets.chomp
year.capitalize!
if month + day + year > 2000
puts "Sum of all the numbers from your birthday date is more than 2000"
else month + day + year < 2000
puts "Sum of all the numbers from your birthday date is less than 2000"
end

day = gets.chomp
Here day is a string. And month + day + year is a string too, only longer. To get integers, call .to_i.
day = gets.to_i # to_i will handle the newline, no need to chomp.
# repeat for month and year
(Of course, once you converted strings to integers, you won't be able to capitalize them. It made no sense anyway.)

Related

Ruby won't divide string

I am trying to divide a user-input age by 2. My code is below:
puts "what is your name?"
name = gets.chomp
puts "when were you born please enter your birthdate"
birthdate = gets.chomp
puts "how old are you "
age = gets.chomp
puts "hello" + name + " wow that is a good day to be born" + "thats a great age"
puts "the half of your age is" + age/2 + " that is good to know"
It does not work.
Your age is a string
age = gets.to_i
Now it's a number. But you can't concatenate a string and a number. Two options:
interpolation
puts "the half of your age is #{age/2} that is good to know"
or
puts "the half of your age is " + (age/2).to_s + " that is good to know"

Ruby, greater than with variable above 1000 not working

here is my code
print("How far in metres are the people away from the spacecraft?")
people = gets.chomp
if people > "600" and (people !~ /\D/)
print ""
else
while !(people > "600" and (people !~ /\D/))
if people < "600" then
print"The people are too close to the launch site, make sure they are 600 metres away from it."
print "How far in metres are the people away from the spacecraft?"
people = gets.chomp
end
if !(people !~ /\D/)
puts "only enter numbers not letters. Please try again:"
people = gets.chomp
end
end
end
print ("The people are away from the launch site.")
I want the last line to appear when 'people' is above 600 but it also has to be a number. but the last line only appears if "people" is below 1000 above 600. Thanks for all the help.
There are images below
1000
789
The problem is that you're comparing Strings instead of Integers.
The strings are being compared alphabetically, so "1000" < "700" will be true, because "1000" appears before "700" when sorted alphabetically.
What you want is to convert the strings into integers before comparing them. Something like this:
people = "700"
if people.to_i > 600
puts "It's greater than 600"
else
puts "It's less than 600"
end
Notice the lack of quotes around 600.
Cast as Integer
When you want to compare integers as numerical values, you need to convert the string stored in people first. Most people will tell you to use String#to_i, but that can be problematic and lead to excessive error-checking code. It's better to use Kernel#Integer, which not only performs the cast but also raises an exception of the string can't be coerced. For example:
print 'Get integer: '
# Remove newlines and thousands separators, then cast as an integer.
people = Integer gets.chomp.delete ','
if people >= 600
puts 'Far enough.'
else
puts 'Not far enough.'
end
This way, if you enter a value such as one thousand or x1000x you'll get an exception like:
ArgumentError: invalid value for Integer(): "x1000x"

Ruby: no implicit conversion of fixnum into string

Trying to solve one of the problems in Chris Pine's book. Asks users to input their first and last names, then it should display the total number of characters of both.
Here's one of many solutions I've come up with:
puts "First name?"
first_name = gets.chomp
puts "Last name?"
last_name = gets.chomp
total = first_name.length.to_i + last_name.length.to_i
puts 'Did you know you have ' + total + ' characters in your name ' + first_name + last_name + '?'
Ruby is pretty strict about the difference between a String and an Integer, it won't convert for you automatically. You have to ask, but you can ask politely:
puts "Did you know you have #{total} characters in your name #{first_name} #{last_name}?"
You can also do the math this way:
puts "Did you know you have #{first_name.length + last_name.length} characters in your name?"
The #{...} interpolation only works inside "double-quoted" strings, but it does convert to a string whatever the result of that little block is. Single quoted ones avoid interpolation, which is sometimes handy.
If you do want to concatenate strings you have to convert manually:
"this" + 2.to_s
Length returns an integer (no need to convert to_i) so change your code to this:
total = first_name.length + last_name.length

ruby Date.month with a leading zero

I have a Date object in Ruby.
When I do myobj.month I get 8. How do I get the date's month with a leading zero such as 08.
Same idea with day.
What I am trying to get at the end is 2015/08/05.
There is the possibility of using a formated string output
Examples:
puts sprintf('%02i', 8)
puts '%02i' % 8
%02i is the format for 2 digits width integer (number) with leading zeros.
Details can be found in the documentation for sprintf
In your specific case with a date, you can just use the Time#strftime od Date#strftime method:
require 'time'
puts Time.new(2015,8,1).strftime("%m")

How do I use the Time class on hash values?

I am working through Chris Pine's Ruby book, and I am slightly confused why my code doesn't quite work.
I have a file called birthdays.txt which has around 10 lines of text which resembles:
Andy Rogers, 1987, 02, 03
etc.
My code as follows:
hash = {}
File.open('birthdays.txt', "r+").each_line do |line|
name, date = line.chomp.split( /, */, 2 )
hash[name] = date
end
puts 'whose birthday would you like to know?'
name = gets.chomp
puts hash[name]
puts Time.local(hash[name])
My question is, why does the last line of code, Time.local(hash[name]) produce this output?:
1987-01-01 00:00:00 +0000
instead of:
1987-02-03 00:00:00 +0000
If you look at the documentation for Time.local,
Time.local doesn't parse a string. It expects you to pass a separate parameter for year, month, and date. When you pass a string like "1987, 02, 03", it takes that to be a single parameter, the year. It then tries to coerce that string into an integer - in this case, 1982.
so, basically, you want to slice up that string into the year, month, and day. there's multiple ways to do this. Here's one (it can be made shorter, but this is the most clear way)
year, month, date = date.split(/, */).map {|x| x.to_i}
Time.local(year, month, date)
line = "Andy Rogers, 1987, 02, 03\n"
name, date = line.chomp.split( /, */, 2 ) #split (', ', 2) is less complex.
#(Skipping the hash stuff; it's fine)
p date #=> "1987, 02, 03"
# Time class can't handle one string, it wants: "1987", "02", "03"
# so:
year, month, day = date.split(', ')
p Time.local(year, month, day)
# or do it all at once (google "ruby splat operator"):
p Time.local(*date.split(', '))
hash = {}
File.open('birthdays.txt').each_line do |line|
line = line.chomp
name, date = line.split(',',2)
year, month, day = date.split(/, */).map {|x| x.to_i}
hash[name] = Time.local(year, month, day)
end
puts 'Whose birthday and age do you want to find out?'
name = gets.chomp
if hash[name] == nil
puts ' Ummmmmmmm, dont know that one'
else
age_secs = Time.new - hash[name]
age_in_years = (age_secs/60/60/24/365 + 1)
t = hash[name]
t.strftime("%m/%d/%y")
puts "#{name}, will be, #{age_in_years.to_i} on #{t.strftime("%m/%d/")}"
end
had to move the Time.local call earlier in the program and then bingo, cheers guys!

Resources