What does this ruby code do? - ruby

I have code here that verifies the number input for zero and floats:
def integer?(input)
input.to_i.to_s == input
end
def float?(input)
input.to_f.to_s == input
end
def valid_number?(input)
integer?(input) || float?(input)
end
loop do # main loop
number1 = ''
loop do
prompt(messages('first_number', LANGUAGE))
number1 = Kernel.gets().chomp()
if valid_number?(number1)
break
else
prompt(messages('not_a_valid_number', LANGUAGE))
end
end
number2 = ''
loop do
prompt(messages('second_number', LANGUAGE))
number2 = Kernel.gets().chomp()
if valid_number?(number2)
break
else
prompt(messages('not_a_valid_number', LANGUAGE))
end
end
end
result = case operator
when '1'
number1.to_i() + number2.to_i()
when '2'
number1.to_i() - number2.to_i()
when '3'
number1.to_i() * number2.to_i()
else
number1.to_f() / number2.to_f()
end
prompt("The answer is: #{result}")
What does this code do in layman's term or in an explanation that a dummy can understand?
def integer?(input)
input.to_i.to_s == input
end
def float?(input)
input.to_f.to_s == input
end
def valid_number?(input)
integer?(input) || float?(input)
end
Any help here? I would appreciate if you could explain it line by line thanks!
Sorry newbie here!

In those functions input is transformed to a number (integer using to_i or float using (to_f)) and then back to string (with to_s). Then the result of those transformations is compared with the input.
It verifies if an input is a number, because if it is not, transformed string will be not equal to the original one.
For instance:
$ "a".to_i.to_s
=> "0"
because to_i returns 0 if string cannot be parsed to an integer (http://ruby-doc.org/core-2.0.0/String.html).

All it's doing is converting a string to an integer / float, converting it back to a string and comparing it to the input string. If the input was a valid integer / float, its converted value will be identical to the input. If, however the input was not a valid number, casting it to an integer or float will turn it into a zero, which when compared to the original input will be different. Here's an example:
irb(main):012:0> "abc".to_i.to_s
=> "0"
irb(main):013:0> "123".to_i.to_s
=> "123"
So as you can see the non-numeric input would fail the check.

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 code Skips A certain part of Program

I am trying to run a calculator program but for some reason it is skipping some parts of the code. Here's my whole ruby codes:
# require yaml file
require 'yaml'
MESSAGES = YAML.load_file('calculator_messages.yml')
LANGUAGE = 'en'
def messages(message, lang='en')
MESSAGES[lang][message]
end
def prompt(key)
message = messages(key, LANGUAGE) # make sure the "messages" method is declared above this line
Kernel.puts("=> #{message}")
end
def integer?(input)
input.to_i.to_s == input
end
def float?(input)
input.to_f.to_s == input
end
def valid_number?(input)
integer?(input) || float?(input)
end
def operation_to_message(op)
word = case op
when '1'
'Adding'
when '2'
'Subtracting'
when '3'
'Multiplying'
when '4'
'Dividing'
end
word
end
prompt('welcome')
name = ''
loop do
name = Kernel.gets().chomp()
if name.empty?()
prompt('valid_name')
else
break
end
end
prompt("Hi #{name}!")
loop do # main loop
number1 = ''
loop do
prompt('first_number')
number1 = Kernel.gets().chomp()
if valid_number?(number1)
break
else
prompt('not_a_valid_number')
end
end
number2 = ''
loop do
prompt('second_number')
number2 = Kernel.gets().chomp()
if valid_number?(number2)
break
else
prompt('not_a_valid_number')
end
end
operator_prompt = <<-MSG
What operation would you like to perform?
1) add
2) subtract
3) multiply
4) divide
MSG
prompt(operator_prompt)
operator = ''
loop do
operator = Kernel.gets().chomp()
if %w(1 2 3 4).include?(operator)
break
else
prompt('choose_number_range')
end
end
prompt("#{operation_to_message(operator)} the two numbers")
result = case operator
when '1'
number1.to_i() + number2.to_i()
when '2'
number1.to_i() - number2.to_i()
when '3'
number1.to_i() * number2.to_i()
else
number1.to_f() / number2.to_f()
end
prompt("The answer is: #{result}")
prompt('next_step')
answer = Kernel.gets().chomp()
break unless answer.downcase().start_with?('y')
end
prompt('goodbye_msg')
Now here are the specific codes that it skips:
1. Displaying the name
prompt("Hi #{name}!")
2. Displaying the adding, subtracting etc. message
prompt("#{operation_to_message(operator)} the two numbers")
3. Finally the part where it prints the actual answer inside the result variable.
result = case operator
when '1'
number1.to_i() + number2.to_i()
when '2'
number1.to_i() - number2.to_i()
when '3'
number1.to_i() * number2.to_i()
else
number1.to_f() / number2.to_f()
end
prompt("The answer is: #{result}")
Do you have any idea why it's skipping this codes?
Problem: As far as I understand, your prompt message tries to translate and probably doesnt find a translation for e.g. "Hi, Felix".
You could check on this theory quickly by changing the message function:
def messages(message, lang='en')
MESSAGES[lang][message] || "NO TRANSLATION FOUND"
end
and observe the output again.
Update
As OP confirmed the theory and requested a 'solution' in the comments, the cheapest one might be this one:
def messages(message, lang='en')
# Look up translation, default to untranslated message.
MESSAGES[lang][message] || message
end

Can I use parenthesis to encapsulate information I want to convert into a string? (ruby)

I want to divide two integers and then convert their result into a string. I have done this by putting the division into parentheses in an attempt to convert the result of the division into a string, instead of just the denominator. There don't seem to be any errors this way but I wanted to double check that this is proper syntax.
Note:#numer and #denom are both integers.
def redfrac
gcd = #numer.gcd(#denom)
if #denom != 0
rednumer = (#numer/gcd).to_s
reddenom = (#denom/gcd).to_s
if reddenom == "1"
puts rednumer
else
puts rednumer + "/" + reddenom
end
else
puts "Cannot divide by 0"
end
end
> (1.0 / 4.0).to_s
=> "0.25"
This syntax is quite legal.
But for this exact task you may use string interpolation:
def redfrac
gcd = #numer.gcd(#denom)
if #denom != 0
rednumer = #numer/gcd
reddenom = #denom/gcd
if reddenom == 1
puts "#{rednumer}"
else
puts "#{rednumer}/#{reddenom}"
end
else
puts "Cannot divide by 0"
end
end

What is the condition on this while loop?

I was reading through Chris Pine's Learn to Program and I encountered this weird code snippet in Chapter 10: Blocks and Procs:
def doUntilFalse firstInput, someProc
input = firstInput
output = firstInput
while output
input = output
output = someProc.call input
end
input
end
buildArrayOfSquares = Proc.new do |array|
lastNumber = array.last
if lastNumber <= 0
false
else
array.pop # Take off the last number...
array.push lastNumber*lastNumber # ...and replace it with its square...
array.push lastNumber-1 # ...followed by the next smaller number.
end
end
What is the condition being checked for, in the above while loop? It doesn't seem to be a shorthand for while output == true.
while output means run the loop till while has any values other than false or nil. As in Ruby everything is a truthy value except these two.

elegant way to check if a string inputed by user is an integer in ruby?

I'm trying to validate that the input a user gives my program via gets is an integer. is_a?(Integer) does not work, as far as i can tell, because gets gets a string from the user, so it will always return false even if the user enters an valid integer (in string form). One would think I could simply use to_i on the input and be done with it, but that raises another issue - "75akjfas".to_i results in 75. So if I relied on to_i to solve my problems, anything starting with numbers will work.
How do I cleanly validate that the value is an integer only, and not a combination of numbers and letters? Or do I need to resort to regex for this?
print "Enter an integer (or try to sneak by something other): "
puts Integer(gets) rescue puts "Hey, that's not an integer!"
How about s.to_i.to_s == s? I'd prefer regex however.
Using regex you could do it like this:
class String
def integer?
!!(self =~ /^[-+]?[0-9]+$/)
end
end
You could use Integer() but you need to be careful with hex, binary, or octal input. http://ruby-doc.org/core-2.3.1/Kernel.html#method-i-Integer
def valid_integer?(string)
begin
!!Integer(string)
rescue ArgumentError
false
end
end
Check this code example for how to use the checked string input by the user
puts "Enter a number: "
user_input = gets.chomp
check = (user_input.to_i.to_s == user_input)
while (!check ) do
puts("Wrong Input, Pls, Enter a number: " )
user_input = gets.chomp
check = (user_input.to_i.to_s == user_input)
end
if user_input.to_i < 0
puts "Number is negative"
elsif user_input.to_i > 0
puts "Number is positve"
else
puts "Number is Zero"
end
Ruby can do it without esoteric solutions:
Integer is a integer
1970.is_a?Integer
true
String is not a integer
"1970".is_a?Integer
false
String to integer is a integer
"1970".to_i.is_a?Integer
true

Resources