Read data from STDIN specific number of times - ruby

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

Related

Basic question Ruby; why is the total variable not updating in the loop

This code is supposed to update the total within the loop, but when I put the total when its broken it doesn't update.
total = 0
while true do
puts "Give me a number"
input = gets.chomp
if input == Integer
total += input
elsif input == "stop"
puts total
break
end
end
input = gets.chomp will result String class. So your logic on if input == Integer it will never be reached. you need to convert it to integer using to_i and input == Integer i never used that kind of syntax to check the classes, i rather use input.is_a?(String). but if you convert to integer first it will never check stop string condition. so maybe
total = 0
while true do
puts "Give me a number"
input = gets.chomp
if input == "stop"
puts total
break
end
total += input.to_i
end
As mentioned in the above comment by mu is too short and dedypuji's answer you have a couple of issue. Here is another variation that I think will work and I think is a little more ruby idiomatic.
total = 0
loop do
print "Give me a number: "
input = gets
break if /stop|^$/ =~ input
total += input.to_i
end
puts total

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

Storing the result of an 'x.times do' loop in a different variable upon each completion?

I have code that runs a 'do' loop a number of times set by a user input, then outputs the result of that loop.
I want to store each result in its own variable once each instance of the loop completes so I can use them later. Right now they're printed in the terminal and the program forgets them.
This is an example of the code I have so far:
input_num.times do
loop_select = rand(1..4)
loop_select = loop_select.round
if loop_select == 1
answer = answer.instance_eval{method.method.method}
set_answer = answer
elsif loop_select == 3
answer = answer.instance_eval{method.method.method}
set_answer = answer
elsif loop_select == 2
answer = answer.instance_eval{method.method.method}
set_answer = answer
elsif loop_select == 4
answer = answer.instance_eval{method.method.method}
set_answer = answer
end
set_answer = print_answer.html
puts set_answer
end
I want set_answer to be something like set_answer_1, set_answer_2, etc. for each iteration of the loop, but I can't set this as a static number because the amount of times vary for each input.
Something like this?
foo = 5
output = foo.times.map do |i|
"loop #{i}"
end
output # => ["loop 0", "loop 1", "loop 2", "loop 3", "loop 4"]
where foo is the input from the user.

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

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

Resources