How to stop this method which is being wrongly initialised in Ruby? - ruby

I have made an if... else loop that's logically correct (I think), but still it calls a block of code even if I enter "N," which stands for a no.
Here's my code:
print "\n"
def reversal
puts "Hello! Let's reverse your name! (Avoid capitals!)\n"
name = gets.chomp
puts "YOUR REVERSED NAME IS!!\n"+name.reverse+"\n\n(Press enter to continue)"
input = gets.chomp
print "So, did you like it? Y or N!\n"
feedback = gets.chomp
end
reversal
if feedback = "Y" || feedback = "y" || feedback = "Yes" || feedback = "YES" || feedback = "yes"
puts "Cool! Would you like to try again? Y or N!\n"
nestedfeedback = gets.chomp
if nestedfeedback = "Y" || nestedfeedback = "y" || nestedfeedback = "Yes" || nestedfeedback = "yes" || nestedfeedback = "YES"
reversal
end
else
puts "I'm sorry for that..."
end
And I'm attaching a picture of what happens here (I'm entering N, but the code block/method is called anyway):

feedback=gets.chomp will define a local variable, only visible inside reversal. When you test it outside reversal, it would be nil, since it has not been defined in that context.
Also, if feedback="Y"... will define feedback to be "Y", not test if it is. Since "Y" and all the other varieties are all truthy, the if will always succeed.
Among many things you can do is:
Use the fact that feedback is a return value from reversal, and use this in the main code instead plain reversal:
feedback = reversal
Test your variables with == in the if.

why dont you make feedback
feedback.downcase!
so that you dont have to worry about cases.

Related

Ruby Endless Loop

I am new to Ruby. I have written the code below, its working about 90% except the else statement. The else statement triggers endless loop. I just want it to ask user to try again. Here is my code
puts "Do you want to print something? (Y / N)"
user = gets.chomp.downcase
answer = true
while answer
if user == "y"
puts "Something"
answer = false
elsif user == "n"
puts " "
answer = false
else
puts "Invalid input! Please enter Y or N"
end
end
Somewhat shorter (note user has gone, the answer is now referred to as answer).
answer = ""
until (answer == "y") or (answer == "n")
puts 'Do you want to print something? (Y/N)'
answer = gets.chomp.downcase
end
Once you exit the else, answer is still true. If you want to re-prompt, you can move your puts and user statement into the loop.
Something like this should work.
while true # (alternately) loop do
puts 'Do you want to print something? (Y/N)'
case gets.chomp.downcase
when 'y'
puts 'foo'
break
when 'n'
puts 'bar'
break
else
puts 'Invalid input! Please enter Y or N'
end
end
You can use break to exit out of your loop instead of setting up another variable. Also, this looks like a good use-case for a case statement to have some explicit cases listed.

A Ruby branching way to allow different user's input options to check for all possible valid answer stored in an array

I have a small code for determining the number of hours per year.
What I am looking for is for a Ruby way to allow different user's input options for all possible valid answer stored in an array
to check if the user provided a valid option by calling include? on the array.
When year consist of 52 weeks.
Week consists of 7 days.
Day consists of 24 hours
My problem comes up when trying to pass different answers for the gets method such as follows:
if answer == "yes" || "yup" || "yeah" || "positive";
if answer == ("yes", "yup", "yeah", "positive")
if answer == ["yes" or "yup" or "yeah" or "positive"]
I receive an error which I couldn't solve
answer = gets.chomp
if answer == "yes" or "yup" or "yeah" or "positive"
puts "Good!"
puts desc_text
my_var = gets.chomp.to_i
if my_var == 3736
puts good_text
else
puts wrong_text
puts bad_text
end
elsif answer == [ "no" || "nop" || "nay || ""negative" ]
puts bad_text
else
puts yes_no
end
I'd like to pass different answer options such as yes, yup, yeah, positive instead of just enclose me to a yes and/or no answer
A more idiomatic Ruby way of allowing for these different user options would be to have all possible valid user input stored in an array, then checking if the user provided a valid option by calling include? on the array. This way, you can update the array with more possible options at a later time. Generally arrays like this are stored as constants, though you can also store them as local variables. I find that for a script like this, variables are fine, but if I'm writing a larger program and I need arrays like this (for example, arrays that specify valid options) in a class, then I use constants to make it easy for other contributors to find them. Another option yet would be to have a configuration file (can be a Ruby file, yaml file, JSON file...) that defines valid options, and then you can load this file when executing your program.
Here is an example of what I mean:
VALID_AFFIRMATIVE_ANSWERS = %w(yes yup yea positive)
VALID_NEGATIVE_ANSWERS = %w(no not nay negative)
answer = gets.chomp
if VALID_AFFIRMATIVE_ANSWERS.include?(answer)
puts "Good!"
puts desc_text
my_var = gets.chomp.to_i
if my_var == 3736
puts good_text
else
puts wrong_text
puts bad_text
end
elsif VALID_NEGATIVE_ANSWERS.include?(answer)
puts bad_text
else
puts yes_no
end
I'm not sure what errors you're receiving, but I'm not sure if you're ever defining some of these variables (for example desc_text etc.).
if code is excetly as you write above your issue is in line written below
elsif answer == [ "no" || "nop" || "nay || ""negative" ]
although it won't work , so the solution for you would be like below
def process_positive_response
my_var = gets.chomp.to_i
if my_var == 3736
puts good_text
else
puts wrong_text
puts bad_text
end
end
answer = gets.chomp
case answer
when 'yes','yup','yeah','positive'
puts "Good!"
puts desc_text
process_positive_response
when 'no', 'nop', 'nay', 'negative'
puts bad_text
else
puts yes_no
end
first why write so much conditions when ruby already does that for you with case statement, and second distribute your code in chunks so it will make your code more traceable.

Ruby factorial loop

Am I doing this wrong? I am trying to write a simple program to ask the user to enter a number until they wish to quit, but when I run the program it gives me an argument error stating bad value for range. what can I do to fix this problem?
var = true
while var == true
print "Enter a number ('Q/q to quit'): "
input = gets.chomp
if input == 'Q' || input == 'q'
var = false
puts "Goodbye!"
else
product = 1
for i in 1..input
product = product * i
end
end
end
puts "#{input}! is #{product}"
The problem is "input" is a string. You can't use it in your range. You need to convert it to a int.
change this:
for i in 1..input.to_i

Is it possible to execute a condition differently in a multiple condition while loop without creating an entire new while loop?

I don't really know how to word this short enough for me to google it.
But is it possible to execute a certain condition in a multiple condition while loop differently, without creating a whole entire while loop.
For example, Is it possible to do something like this
while num == "" || num == "0"
#ENTER CODE
Instead of doing this
while num == ""
print "YOU MUST ENTER A NUMBER!"
num = gets.chomp
end
while num == "0"
print "ZERO IS NOT A VALID NUMBER!"
num = gets.chomp
end
I want to know is it possible to do this, but make it look more visually appealing and concise.
This should do the trick, one loop and use conditionals for which error message to print.
while num == "" || num == "0"
print "YOU MUST ENTER A NUMBER!" if num == ""
print "ZERO IS NOT A VALID NUMBER!" if num == "0"
num = gets.chomp
end
You could write something like this:
while num.to_i.zero?
case number
when ''
print 'YOU MUST ENTER A NUMBER!'
when '0'
print 'ZERO IS NOT A VALID NUMBER!'
end
num = gets.chomp
end
This works, because to_i returns 0 for both the string "0" and nil.
Furthermore I would suggest to change the error message to simplify the code even more:
while num.to_i.zero?
print 'Please enter a number greater then zero'
num = gets.chomp
end

Why isn't my loop working?

I can't get this program to respond properly to user input. Various looping techniques either only run the block once or run the block infinitely no matter what the user inputs (I've tried case and while as well). Here's the most recent method I've tried:
work_summary = []
begin
# code that runs a sprint and adds results to the work_summary array
puts "Would you like to add a sprint, Y/N?"
sprint = gets.to_s
end until sprint == "N"
print work_summary, "\n"
Ruby never objects to my syntax with any of the various methods, but it also never works.
You need
sprint = gets.chomp
gets returns string with trailing "\n".
http://web.njit.edu/all_topics/Prog_Lang_Docs/html/ruby/syntax.html#begin
Begin is typically used for exception handling. I think you're looking for a while loop.
Here is an example
work_summary = []
while true
puts "Would you like to add a sprint?"
sprint = gets.chomp
if sprint == "N"
break
elsif sprint == "Y"
puts "What's your time?"
time = gets.chomp
work_summary << time
else
puts "I didn't understand your request. Enter Y or N"
end
end
I found two possibility over here which is suitable for you
First one is
while true
puts "Would you like to add a sprint?"
sprint = gets.chomp
if sprint == "N"
break
elsif sprint == "Y"
puts "What's your time?"
time = gets.chomp
work_summary << time
else
puts "Wrong request. Enter Y or N"
end
end
Here Lopp will run until break Doesn't get executed
Second thing you can Modify 1 Line in your code which is
sprint = gets.chomp
this will extract last special character of your string which is generated by gets and work fine in your case

Resources