how to break a loop? - ruby

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 ...

Related

Loop error for multiple conditions

I have this loop:
puts "Welcome to the Loop Practice Problems"
puts " Write a number between 1 and 10, but not 5 or else...."
ans = gets.chomp!
if ans < 1
puts "Tf bruh bruh"
elsif ans > 10
puts "Now you just playin"
elsif x == 5
print "You wildin B"
else
puts "Fosho that's all I require"
end
It doesn't run properly, and I'm trying to understand why. If you can help me with this, I'd appreciate it.
If you know a good site for practice problems, I'd love to try it. I checked out Coderbyte and Code Kata, but the way they're set up doesn't look right, and they don't have questions to solve for fundamentals.
The issue here is that you're not converting ans to a number, but you're comparing it to one. ans is going to be a string.
In Ruby, when you compare a number to a string, Ruby says that the two aren't equal:
"1" == 1
=> false
You can reproduce the problem with this code:
puts "Welcome to the Loop Practice Problems"
puts " Write a number between 1 and 10, but not 5 or else...."
ans=gets.chomp!
p ans
The p method will output an "inspected" version of that object, (it's the same as doing puts ans.inspect). This will show it wrapped in quotes, which indicates that it's a string.
You probably want to do this:
ans = gets.chomp!.to_i
The to_i method here will convert the number to an integer, and then your comparisons will work correctly.
You have to convert input string type object into integer type
ans = gets.chomp!.to_i #input string convert into integer.
if ans < 1
puts "Tf bruh bruh"
elsif ans > 10
puts "Now you just playin"
elsif x == 5
print "You wildin B"
else
puts "Fosho that's all I require"
end

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).

Ruby code efficiency

Is there a way to make this code shorter and simpler?
loop do
if possibleSet.split(" ").map(&:to_i).any? {|e| (e<0 || e>12)}
print "Please enter valid numbers (between 1 and 12): "
possibleSet = gets
errorinput = false
else
errorinput = true
end
break if errorinput
end
Refactored a bit :)
loop do
print "Please enter valid numbers (between 1 and 12): "
possibleSet = gets.chomp
break unless possibleSet.split(" ").map(&:to_i).any? {|e| (e<0 || e>12)}
end
The code below will check input for correctness:
input = loop do
print "Please enter valid numbers (between 1 and 12): "
# ⇓⇓⇓ as many spaces as user wants
input = gets.chomp.split(/\s+/).map(&:to_i) rescue []
break input unless input.empty? || input.any? { |i| !(0..12).include? i }
end
This parses the user input in an array (not exactly the same behavior, but I hope it is cleaner and you can work from there)
set = []
until set.all? {|i| (1..11).include?(i) } && !set.empty? do
set = gets.split(' ').map(&:to_i)
end

Ruby: function/method positions

I have this factorial app that's supposed to go infinite if answer is always "y".
def continue?
answer = gets
if answer.downcase == "y"
main
elsif answer.downcase == "n"
exit
else
"This means n to me. Follow the rules next time. Bye."
end
end
def main
p "Enter any Integer"
out = gets
num = out.to_i
def factorial(num)
sum = num
(num-1).times {sum = sum * (num - 1); num = num-1}
sum
end
p factorial(num)
p "Do you want another number"
continue?
end
main
At first, #continue? was at the end of the app, but then when I called continue in #main I'd get an error for non-existing Method. So, I moved #continue? to the top but now I can't call #main because of the same method error again. I can put #continue? inside #main method but I don't think it will do a lot. Is there a better way for handling this kind of situation?
If my code is off or my practice is not the best please let me know. And I'd use #inject for factorial but I was working with ruby 1.8.5 so I had to do what I could.
First of all, calling main from another function is weird because main should only be called once when the program starts.
Second, if you do it this way you're going to run out of memory because your callstack is going to keep growing (main, continue, main continue, ...)
Why don't you make continue? return a true or false value. Then in main you can write
begin
p "Enter any Integer"
out = gets
num = out.to_i
def factorial(num)
sum = num
(num-1).times {sum = sum * (num - 1); num = num-1}
sum
end
p factorial(num)
p "Do you want another number"
end while continue?
You could put the condition in a while loop instead of calling the function every time. Also, take care with gets method, you should strip the input.
def continue?
answer = gets.strip
if answer.downcase == "y"
true
elsif answer.downcase == "n"
false
else
p "This means n to me. Follow the rules next time. Bye."
false
end
end
def main
begin
p "Enter any Integer"
out = gets
num = out.to_i
def factorial(num)
sum = num
(num-1).times {sum = sum * (num - 1); num = num-1}
sum
end
p factorial(num)
p "Do you want another number"
end while continue?
end
main
You've got a couple of problems. First, when you do answer = gets what you're getting isn't just a letter, it's a letter followed by a linefeed, e.g. 'y\n'. The solution is to use str#chomp. Also, you're not actually showing anything when a letter other than 'y' or 'n' is entered. Here's the fixed method:
def continue?
answer = gets.chomp
if answer.downcase == "y"
main
elsif answer.downcase == "n"
exit
else
puts "This means n to me. Follow the rules next time. Bye."
end
end

Read data from STDIN specific number of times

I am writing a code that is supposed to read from STDIN exactly n number of times.So lets say 3 times.What is the best way to do that ?
I tried this
counter = 0
while sentence = gets.chomp && counter < 3 do
...
counter += 1
end
but for some strange reason, sentence variable inside loop is Boolean ?
You can do as below:
n.times { sentence = gets.chomp }
or
n.times do
sentence = gets.chomp
# your code here
end
Operator precedence. The line:
while sentence = gets.chomp && counter < 3 do
Is being interpretted as
while sentence = ( gets.chomp && counter < 3 ) do
So, you could do this:
while ( sentence = gets.chomp ) && counter < 3 do
That explains why you got true or false values into sentence, and the third option should fix this, so your code is very close to working. However, it is probably more usual in Ruby to see solutions like Babai's

Resources