STDIN.read.split("\n").each do |a|
a=gets.to_i
if a >=0
puts "a is positive"
end
end
Output
C:\Ruby221-x64\programs>ruby test2.rb
5
test2.rb:3:in `read': Interrupt
from test2.rb:3:in `<main>'
Question: Why is my Ruby Code not going into the if?
Also Is the above code a way to handle continuous input? how will my code know after which input to stop. I had to press Ctrl-C to come out
Your gets call is superfluous because the STDIN.read.split("\n").each do |a| already reads the inputs into a. So remove the gets:
STDIN.read.split("\n").each do |a|
if a.to_i >= 0
puts "#{a} is positive"
end
end
Note that the I/O is buffered, and you're operating on a block basis, so you'll get:
Enter these inputs:
5
4
3
Press Ctrl-D to end the input (for Linux) or Ctrl-Z (for Windows), then you'll get results:
5 is positive
4 is positive
3 is positive
=> ["5", "4", "3"]
If you want this to be more interactive, then don't use the STDIN... each construct, but just do a loop with gets.to_i. For example:
loop do
a = gets
break if a.nil? # Exit loop on EOF (ctrl-D)
if a.to_i > 0
puts "a is positive"
end
end
If I put this into a file, say foo.rb, then I get:
OS_Prompt> ruby foo.rb
3
a is positive
5
a is positive
2
a is positive
-1
-3
2
a is positive
[ctrl-D]
OS_Prompt>
And it will quit the loop on ctrl-D since that will cause gets to return nil. Although in Windows, it might want Ctrl-Z.
▶ loop do
▷ b = STDIN.gets.to_i
▷ break if b.zero?
▷ puts b > 0 ? 'positive' : 'negative'
▷ end
#⇒ 5
# positive
# -4
# negative
# 0
# => nil
STDIN.read.split("\n").each do |a|
This line is already taking input continuously then whats the need of gets.
while(true)
b= gets.chomp.to_i
puts b >=0 ? "b is positive" : "b is negative"
end
Here chomp is used to remove \n from the input
Related
Learn Ruby the Hard Way asks to rewrite a script:
i = 0
numbers = []
while i < 6
puts "At the top i is #{i}"
numbers.push(i)
i += 1
puts "Numbers now: ", numbers
puts "At the bottom i is #{i}"
end
puts "The numbers: "
numbers.each {|num| puts num}
using for-loops and the (0 .. 6) range. The only solution I can find to work uses the for-each construct, which the author says to avoid:
def range_loop(increment, upper_limit)
numbers = []
for number in (0...upper_limit)
puts "The number is : #{number}"
numbers.push(number)
end
puts "The numbers: "
for number in numbers
puts number
end
end
range_loop(1, 6)
How can I write this script using the each construct?
You can use Range object and Enumerable#each method for this goal:
(0...6).each do |i|
#some code here
end
You could also use upto
0.upto(6) {|x| p "The number is #{x}"}
def is_even?(n)
remainder_when_divided_by_2 = n % 2
if remainder_when_divided_by_2 == 0
return true
else
return false
end
end
def is_odd?(n)
return ! is_even?(n)
end
puts "1 is_even? #{is_even?(1)} - is_odd? #{is_odd?(1)}"
puts "2 is_even? #{is_even?(2)} - is_odd? #{is_odd?(2)}"
puts "3 is_even? #{is_even?(3)} - is_odd? #{is_odd?(3)}"
puts "4 is_even? #{is_even?(4)} - is_odd? #{is_odd?(4)}"
puts "5 is_even? #{is_even?(5)} - is_odd? #{is_odd?(5)}"
puts "6 is_even? #{is_even?(6)} - is_odd? #{is_odd?(6)}"
def is_even_and_divisible_by_five?(n)
remainder_when_divided_by_five = n % 5
if (remainder_when_divided_by_five == 0) && (is_even?(n) == true)
return true
else
return false
end
end
puts "5 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(5)}"
puts "10 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(10)}"
puts "15 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(15)}"
puts "20 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(20)}"
puts "25 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(25)}"
puts "30 is_even_and_divisible_by_five? #{is_even_and_divisible_by_five?(30)}"
The problem was I had not called the method is_even_and_divisible_by_five in the puts commands at the bottom of the code. I called it is_even_and_divisble_by_5. Then in the if statement in the is_even_and_divisble_by_five method, I left of the (n) arguement from Is_even. Thank you all very much!
Even (divisible by two) and divisible by five also means "divisible by ten":
def is_even_and_divisible_by_five?(n)
n % 10 == 0
end
You called
is_even_and_divisible_by_5?
instead of
is_even_and_divisible_by_five?
Also is_even? function is undefined. I guess there was some mistake made with its defining or maybe even not-defining. So maybe when you defined is_even_and_divisible_by_five?(n) function there were some other errors and It was not defined too. Plus I think here is much easier solution:
def is_even_and_divisible_by_five?(n)
n % 5 == 0 && n.even?
end
In Ruby You don't have to use return all the time. You should use it quite rarely. The reason is ruby functions return last calculated value by default. And nearly everything is returning value in ruby, even blocks and If-Else statements. If you open irb console and try to do some code, for example:
a = 5
=> 5
Second line is what first line returns. You can do some experiments like this by your own with any type of conditions you like.
The name of your method is is_even_and_divisible_by_five?, not is_even_and_divisible_by_5?.
is_even? is not defined by itself
Here a shorter version of your method
def is_even_and_divisible_by_five? n
0 == n % 5 + n % 2
end
I am looking for a more elegant, 'Ruby-ists' way to do the following. Is there any cleaner way to do this?
i=0
array.each do |x|
break if x.empty?
puts x
i+=1
break if i>4
end
I saw that you were calling #empty? on the elements in your array and quitting when you see the first empty element. If you want to preserve that behavior, you could do:
array.first(4).each do |x|
break if x.empty?
puts x
end
A fancier way would be:
array.take_while { |i| !i.empty? }.first(4).each do |i|
puts i
end
I am not sure how many elements you want to print; please note that my examples will print at most 4 elements, whereas your code was printing up to 5.
I'd suggest Array#first as follows:
array.first(4).each do |x|
puts x
end
If you only want to accept the first so many non-nil entries, then filter them out using Array#compact:
array.compact.first(4).each do |x|
puts x
end
If you are concerned about empty values then you could still chain the filters using Array#reject:
array.reject(&:empty?).first(4).each do |x|
puts x
end
Another way:
def printem(a,n)
puts a[0, [a.index(&:empty?) || n, n].min]
end
printem [[], [2],[3],[4],[5],[6]], 4
# <prints nothing>
printem [[1],[2], [],[4],[5],[6]], 4
# 1
# 2
printem [[1],[2],[3],[4],[5],[6]], 4
# 1
# 2
# 3
# 4
printem [[1],[2],[3],[4],[5],[6]], 7
# 1
# 2
# 3
# 4
# 5
# 6
In Kernel#loop documentation, there is an example that uses break in order to break out of the loop. Otherwise, the documentation talks about rasing a StopIteration error.
I tried them both:
i=0
loop do
puts i
i+=1
break if i==10
end
i=0
loop do
puts i
i+=1
raise StopIteration if i==10
end
The output is the same. Are there differences between the two approaches? I think that there should be, otherwise why bother to define an error class and all the managements that come with it?
break is a keyword in ruby, which terminates the most internal loop, whether it be loop, or for, and a few more (see here).
StopIteration is an exception, which is caught by Kernel.loop (see here).
So in your scenario, they are the same, but in a different scenario, they will act differsntly:
puts "first run"
for i in 0..20 do
puts i
break if i==10
end
puts "first done"
puts "second run"
for i in 0..20 do
puts i
raise StopIteration if i==10
end
puts "second done" # <= will not be printed
Here is a scenario where StopIteration can be utilized when break cannot:
puts "first run"
def first_run(i) # will not compile
puts i
break if i==10
end
i=0
loop do
first_run(i)
i+=1
end
puts "first done"
puts "second run"
def second_run(i)
puts i
raise StopIteration if i==10
end
i=0
loop do
second_run(i)
i+=1
end
puts "second done"
Here is another use-case, which uses the fact the Enumerator.next throws a StopIteration error when the Enumerator has reached the end:
enum = 5.times.to_enum
loop do
p enum.next
end
will print
0
1
2
3
4
Thanks Cary for this example.
There are two uses of the break keyword.
First: the break keyword, when in a block, causes the method that the block was passed to to return. If you pass an argument to break, the return value of the method will be that argument. Here is an example:
def a
puts 'entering method a'
yield
puts 'leaving method a'
end
result = a { break 50 }
puts result
This will print:
entering method a
50
Second: the break keyword can cause a while, until, or for loop to terminate. Here is an example:
i = 0
result =
while i < 5
i += 1
puts i
break 75 if i == 3
end
puts result
This will print:
1
2
3
75
Your example with Kernel#loop makes use of the first case, causing the loop method to return.
StopIteration is an exception which only works with Kernel#loop as far as I can tell. For example:
infinite_loop = Enumerator.new do |y|
i = 0
while true
y << i
i += 1
end
end
infinite_loop.each do |x|
puts x
raise StopIteration if x == 4
end
Fails because StopIteration is uncaught, however:
x = 0
loop.each do
puts x
x += 1
raise StopIteration if x == 4
end
Catches StopIteration and exits.
I keep getting the following error message:
text.rb:2:in `<main>': undefined method `choices' for main:Object (NoMethodError)
But I can't seem to understand why my method is "undefined":
puts "Select [1] [2] [3] or [q] to quit"; users_choice = gets.chomp
choices(users_choice)
def choices (choice)
while choice != 'q'
case choice
when '1'
puts "you chose one!"
when '2'
puts "you chose two!"
when '3'
puts "you chose three!"
end
end
end
This is because you are calling method choices, before defining it. Write the code as below:
puts "Select [1] [2] [3] or [q] to quit"
users_choice = gets.chomp
def choices (choice)
while choice != 'q'
case choice
when '1'
break puts "you chose one!"
when '2'
break puts "you chose two!"
when '3'
break puts "you chose three!"
end
end
end
choices(users_choice)
I used break, to exit from the while loop. Otherwise it will create an infinite loop.
def main
puts "Select [1] [2] [3] or [q] to quit"; users_choice = gets.chomp
choices(users_choice)
end
def choices (choice)
while choice != 'q'
case choice
when '1'
puts "you chose one!"
break
when '2'
puts "you chose two!"
break
when '3'
puts "you chose three!"
break
end
end
end
main
The method only needs to be called prior to being executed. Here I wrap the definition in the main method, but only call main after the definition of choices().
I was getting the same error running Ruby in Eclipse working out the App Academy practice exercises. I forgot to add "object." to the supplied test cases. The following syntax works:
#!/usr/bin/ruby
class Prime
# Write a method that takes in an integer (greater than one) and
# returns true if it is prime; otherwise return false.
#
# You may want to use the `%` modulo operation. `5 % 2` returns the
# remainder when dividing 5 by 2; therefore, `5 % 2 == 1`. In the case
# of `6 % 2`, since 2 evenly divides 6 with no remainder, `6 % 2 == 0`.
# More generally, if `m` and `n` are integers, `m % n == 0` if and only
# if `n` divides `m` evenly.
#
# You would not be expected to already know about modulo for the
# challenge.
#
# Difficulty: medium.
def primer(number)
if number < 2
return false
end
i = 10
while i > 1
if number > i && number != i
if number % i == 0
return false
end
end
i -= 1
end
return true
end
end
object = Prime. new
# These are tests to check that your code is working. After writing
# your solution, they should all print true.
puts("\nTests for #primer")
puts("===============================================")
puts('primer(2) == true: ' + (object.primer(2) == true).to_s)
puts('primer(3) == true: ' + (object.primer(3) == true).to_s)
puts('primer(4) == false: ' + (object.primer(4) == false).to_s)
puts('primer(9) == false: ' + (object.primer(9) == false).to_s)
puts("===============================================")