Ruby code Skips A certain part of Program - ruby

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

Related

In Ruby, is there a way to have the user loop back through a conditional statement if they input the wrong range?

I wonder if there is a way to use the if-else statements to trigger a loop that has the user re-enter a valid input? I have tried using the While loop as that type of structure technically works, but I cannot get the correct implementation. As of now, I have used an if-else conditional to individually test for each number in the valid range, and if the user inputs any of those values, it moves on. The else statement tells the user it is incorrect, but I can't seem to figure out a way to loop the user back until they enter a valid number.
This is the code I am working with:
class Humanoid < Player
def play()
userinput = print 'Enter your move [1 - 5]: '
input = gets&.rstrip
if input == '5'
return input
elsif input == '4'
return input
elsif input == '3'
return input
elsif input == '2'
return input
elsif input == '1'
return input
else
return "That is not an option, choose again"
end
end
end
Is it possible to prompt the user to enter another number if it wasn't correct? I feel like it should be but I am currently stumped on what to do.
I would use a simple loop that runs forever unless you explicitly return (or break) from it:
class Humanoid < Player
def play()
loop do
print 'Enter your move [1 - 5]: '
input = gets.chomp
if %w[1 2 3 4 5].include?(input)
return input
else
puts "That is not an option, choose again"
end
end
end
end
Additionally, I cleaned up your conditions.
I would write it like this:’
loop do
userinput = print 'Enter your move [1 - 5]: '
input = gets&.rstrip
if input == '5'
return input
elsif input == '4'
return input
elsif input == '3'
return input
elsif input == '2'
return input
elsif input == '1'
return input
puts "That is not an option, choose again"
end
Basically, this just makes it repeat forever until a value is returned. If none is, then the issue is printed and it loops again.

ruby method looping without loop

hi I am having a problem with a method i have written. When the method has finished executing it runs its first 2 lines again even though there is no loop. can anyone tell me why?
here is the code
def print(students)
if sort_by?("letter") then students = letter_sort(students) end
if sort_by?("cohort") then students = cohort_sort(students) end
print_header
i = 0
until i = students.length do
student_name = get_student_name(students[i][:name])
puts "#{i+1}. #{student_name} (#{students[i][:cohort]} cohort)"
i = i + 1
end
end
The two if statements at the top are the ones being executed. Here is the sort_by? method I've written as well.
def sort_by?(string)
puts "would you like to sort by #{string}?"
puts "Enter y/n:"
input = gets.chomp.downcase
while input != "n" or input != "y"
if input == "n"
return false
elsif input == "y"
return true
end
end
end
Any help at all would be appreciated.

Ruby - How to Execute something and then Break inside IF block?

EDIT: Someone pointed out that I needed to break correctly so I am editing the question
Scenario:
Please see following code:
print "UserID: "
uid = $stdin.gets.chomp
print "Password: "
pwd = $stdin.gets.chomp
usr_inp = "#{uid};#{pwd}"
login_status = -1
# login_info.txt - "#{userid};#{password}" - format
File.open(File.join(File.dirname(__FILE__), 'login_info.txt'), "r") do |f|
f.each_line do |line|
puts line
if (line.chomp == usr_inp)
login_status = 1
elsif (line.chomp != usr_inp && line.include?(uid)) #case a person inputs invalid password
login_status = 0
elsif (line.chomp != usr_inp && !(line.include?(uid))) #case a person inputs an invalid id
login_status = 2
end
end
end
if (login_status == 1)
puts "\nLogged in successfully: #{uid}"
elsif (login_status == 2)
puts "\nSorry, that Employee does not exist."
elsif (login_status == 0)
puts "\nLogin failed.\nPlease check credentials."
end
Problem:
break if (condition) exists in Ruby. But I don't waht that.
I want to do something like:
if (condition x)
(do something)
break
elsif (condition y)
(do something else)
break
else
(whatever)
end
Maybe I am not understanding how ruby code works. Whenever I try to put the break as I want to use it, it associates with the next elsif.
Please help.
It depends on what you need and where you need it.
A script like this:
condition = 1
case condition
when 1
puts 'one'
break
when 2
puts 'two'
else
puts 'Other %s' % condition
end
puts 'end'
has a syntax error. break leaves a loop and there is no loop.
But with a loop, this works:
[1,2,3].each{|condition|
case condition
when 1
puts 'one'
break
when 2
puts 'two'
else
puts 'Other %s' % condition
end
puts 'end'
}
puts 'very end'
The output is:
one
very end
You see, the loop is stopped.
If you want to continue the loop with the next element, you need next (sorry, I'm just not aware what break is doing really in Java - it's been a long time since my last Java program):
[1,2,3].each{|condition|
case condition
when 1
puts 'one'
next
when 2
puts 'two'
else
puts 'Other %s' % condition
end
puts 'end %s' % condition
}
puts 'very end'
The result:
one
two
end 2
Other 3
end 3
very end
When you are not inside a loop (like in your code snippet), you may use exit (leave the program) or return (leave a method).

What does this ruby code do?

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.

how to break a loop?

when 1
add(first_number, second_number)
begin
print "Calculate again? [y/n]: "
response = gets.chomp
if response.downcase =~ /[n]/
break
elsif response.downcase =~ /[^ny]/
puts "please input y or n"
else response.downcase =~ /[y]/
puts "yay"
end
end
EDIT
Profuse apologies. This is a changed version.
My question as it stands now is how do I keep repeating the question of 'please input y or n' when a user chooses to enter other than those characters?
the begin <code> end while <condition> is regretted by Ruby's author Matz. Instead, he suggests to use Kernel#loop,
e.g.
The while statement modifier normally checks the condition before entering the loop. But if the while statement modifier is on a begin ... end statement, then it loops at least once. Same with the until statement modifier.
Example of while
val = 0
begin
val += 1
puts val
end while val % 6 != 0
Example of until
val = 0
begin
val += 1
puts val
end until val % 6 == 0
As you wants to know about breaks..
Example of break unless
val = 0
loop do
val += 1
puts val
break unless val %6 != 0
end
Example of break if
val = 0
loop do
val += 1
puts val
break if val %6 == 0
end
Output:
Above all four of these examples print the numbers 1, 2, 3, 4, 5, 6.
I hope this answer makes you clear..
For your reference I have found very nice Example of Code about Table of Contents You can Execute(Run) that code here online and check the result. If my answer somehow helps you then you can accept as answered. :)
I would probably extract the confirmation into a method, something like:
def confirm(message)
loop do
print "#{message} [y/n]: "
case gets.chomp
when 'y', 'Y' then
return true
when 'n', 'N'
return false
else
puts 'please input y or n'
end
end
end
And use it like:
loop do
puts 'Calculating...'
sleep 5 # calculation
puts '42'
break unless confirm('Calculate again?')
end
Usage:
$ ruby test.rb
Calculating...
42
Calculate again? [y/n]: maybe
please input y or n
Calculate again? [y/n]: y
Calculating...
42
Calculate again? [y/n]: n
$
You should run your loopy method in a separate thread, and then
kill that thread when the user presses any key on the keyboard ...

Resources