unexpected return (local jumperror) - ruby

def getPrime(testNumber)
temp1=testNumber -1;
bIsPrime = false;
while (temp1 > 1) do
bIsPrime = ((testNumber % temp1) == 0)
puts("Check 1 #{((testNumber % temp1) == 0)}, temp1=#{temp1} ");
if ($bIsPrime)
break;
else
temp1 = temp1-1;
end
end
return bIsPrime
end
puts("Enter any number to know if it's Prime or not");
testNumber = gets()
returnVal = getPrime(Integer(testNumber));
puts("Is enternered number Pime? #{return}");
I have just started with Ruby...So to begin with i tried to write a prime number program.
This thing is giving error "unexpected return"
Any help would be great. Thanks.

return is reserved. You cannot use it as a variable name, or otherwise, other than to return.
I believe you meant puts("Is entered number prime? #{!returnVal}");

Don't check this answer, Adam was first. But here's more info
As Adam says in his answer, the problem is that you said
puts("Is enternered number Pime? #{return}");
What was happening
Ruby evaluates whatever is inside the #{ foo } construct--if it is in an interpolated string, such as
puts "1 + 1 = #{1+1}" ==>> Will print 1 + 1 = 2
The resulting value is then converted (coerced) to be a string.
In your case, you told ruby to evaluate the return statement, which didn't make any sense in the context. Hence the slightly weird error message.

although you already have your answer I thought it would be helpful to drop this here, it follows the same idea you're using in your code:
def is_prime?(test_number)
(2..test_number-1).reverse_each do |i|
divisible = (test_number % i == 0)
puts "Check ##{test_number-i}, divisible=#{divisible}, temp=#{i}"
return false if divisible
end
return true
end
puts "Enter any number to know if it's prime or not"
test_number = gets.chomp.to_i
puts "Is entered number prime? #{is_prime?(test_number)}"

Related

Ruby while loop keeps repeating regardless of input

I wrote a simple guess the number game. But it keeps looping even when I input the correct number. Please help, thanks!
puts "Pick a number between 0 - 1000."
user_guess = gets.chomp.to_i
my_num = rand(831)
guess_count = 0
until user_guess == my_num do
if user_guess == my_num
guess_count += 1
puts "you got it!"
elsif user_guess <= 830
guess_count += 1
puts "higher"
else user_guess >= 1000
guess_count += 1
puts "lower"
end
end
puts "You guessed my number in #{guess_count} attempts. Not bad"
The part of the code that asks for a number from the user is outside the loop, so it will not repeat after the answer is checked. If you want to ask the user to guess again when their guess is wrong, that code needs to be inside the loop.
my_num = rand(831)
guess_count = 0
keep_going = true
while keep_going do
puts "Pick a number between 0 - 1000."
user_guess = gets.chomp.to_i
if user_guess == my_num
guess_count += 1
puts "you got it!"
keep_going = false
elsif user_guess <= 830
guess_count += 1
puts "higher"
else user_guess >= 1000
guess_count += 1
puts "lower"
end
end
puts "You guessed my number in #{guess_count} attempts. Not bad"
This code still has some bugs in it that stops the game from working correctly though, see if you can spot what they are.
As #Tobias has answered your question I would like to take some time to suggest how you might make your code more Ruby-like.
Firstly, while you could use a while or until loop, I suggest you rely mainly on the method Kernel#loop for most loops you will write. This simply causes looping to continue within loop's block until the keyword break is encountered1. It is much like while true or until false (commonly used in some languages) but I think it reads better. More importantly, the use of loop protects computations within its block from prying eyes. (See the section Other considerations below for an example of this point.)
You can also exit loop's block by executing return or exit, but normally you will use break.
My second main suggestion is that for this type of problem you use a case statement rather than an if/elsif/else/end construct. Let's first do that using ranges.
Use a case statement with ranges
my_num = rand(831)
guess_count = 0
loop do
print "Pick a number between 0 and 830: "
guess_count += 1
case gets.chomp.to_i
when my_num
puts "you got it!"
break
when 0..my_num-1
puts "higher"
else
puts "lower"
end
end
There are a few things to note here.
I used print rather than puts so the user will enter their response on on the same line as the prompt.
guess_count is incremented regardless of the user's response so that can be done before the case statement is executed.
there is no need to assign the user's response (gets.chomp.to_i) to a variable.
case statements compare values with the appropriate case equality method ===.
With regard to the last point, here we are comparing an integer (gets.chomp.to_i) with another integer (my_num) and with a range (0..my_num-1). In the first instance, Integer#=== is used, which is equivalent to Integer#==. For ranges the method Range#=== is used.
Suppose, for example, that my_num = 100 and gets.chomp.to_i #=> 50 The case statement then reads as follows.
case 50
when 100
puts "you got it!"
break
when 0..99
puts "higher"
else
puts "lower"
end
Here we find that 100 == 50 #=> false and (0..99) === 50 #=> true, so puts "higher" is displayed. (0..99) === 50 returns true because the integer (on the right of ===) is covered by the range (on the left). That is not the same as 50 === (0..90), which loosely reads, "(0..99) is a member of 50", so false is returned.
Here are a couple more examples of how case statements can be used to advantage because of their reliance on the triple equality method.
case obj
when Integer
obj + 10
when String
obj.upcase
when Array
obj.reverse
...
end
case str
when /\A#/
puts "A comment"
when /\blaunch missiles\b/
big_red_button.push
...
end
Use a case statement with the spaceship operator <=>
The spaceship operator is used by Ruby's Array#sort and Enumerable#sort methods, but has other uses, as in case statements. Here we can use Integer#<=> to compare two integers.
my_num = rand(831)
guess_count = 0
loop do
print "Pick a number between 0 and 830: "
case gets.chomp.to_i <=> my_num
when 0
puts "you got it!"
break
when -1
puts "higher"
else # 1
puts "lower"
end
end
In other applications the spaceship operator might be used to compare strings (String#<=>), arrays (Array#<=>), Date objects (Date#<=>) and so on.
Use a hash
Hashes can often be used as an alternative to case statements. Here we could write the following.
response = { -1=>"higher", 0=>"you got it!", 1=>"lower" }
my_num = rand(831)
guess_count = 0
loop do
print "Pick a number between 0 and 830: "
guess = gets.chomp.to_i
puts response[guess <=> my_num]
break if guess == my_num
end
Here we need the value of gets.chomp.to_i twice, so I've saved it to a variable.
Other considerations
Suppose we write the following:
i = 0
while i < 5
i += 1
j = i
end
j #=> 5
j following the loop is found to equal 5.
If we instead use loop:
i = 0
loop do
i += 1
j = i
break if i == 5
end
j #=> NameError (undefined local variable or method 'j')
Although while and loop both have access to i, but loop confines the values of local variables created in its block to the block. That's because blocks create a new scope, which is good coding practice. while and until do not use blocks. We generally don't want code following the loop to have access to local variables created within the loop, which is one reason for favouring loop over while and until.
Lastly, the keyword break can also be used with an argument whose value is returned by loop. For example:
def m
i = 0
loop do
i += 1
break 5*i if i == 10
end
end
m #=> 50
or
i = 0
n = loop do
i += 1
break 5*i if i == 10
end
n #=> 50
1. If you examine the doc for Kernel#loop you will see that executing break from within loop's block is equivalent to raising a StopIteration exception.

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, random number generator and if statement

After running this program, it only ever returns "miss"
What have I done wrong?
def method
print "Enter number from 0 to 4"
x = gets.chomp
num = rand(5)
if x == num
puts "hit"
else
puts "miss"
end
end
while 1==1
method
end
thanks
gets.chomp results in a String. Comparing a String to a number with equality will never be true, because they are completely different types.
You should convert x to an integer before comparison, using String#to_i:
x = gets.chomp.to_i
Also, while 1==1 is a bit strange. This is more readable:
while true
method
end
Or even better:
loop { method }
You are reading a string from $stdin:
Change
x = gets.chomp
to
x = gets.chomp.to_i
Hope this helps
Reference
String#to_i

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

Reservation System

Can anyone please tell me what I should be using and why this method isn't correct? The code doesn't work, I know, I just want to know how I can interface with the array for this type of thing.
Thank you.
Code:
$i = 1
$f = 0
$c = 0
answer = ""
loop do
puts "Welcome\n"
puts "If you'd like to fly in first class, Press 1. For coach, Push 2."
answer = STDIN.gets
answer.chop!
break if answer =~ /1|2/
if answer == 1 then
$i += 1.each
$available.at(0..4)
end
if answer == 2 then
$i += 1.each
$available.at(5..19)
else
puts "Invalid number, enter 1 or 2."
Console_Screen.pause
end
end
puts "Here is your boarding pass. You are in seat " + $i.to_s
For first class, you can do something like this:
next_first = (0..4).find { |i| $available[i] != 1 }
If that gives you a next_available that is nil then first class is full, otherwise you have the index of the next available first class seat.
Similarly for coach:
next_coach = (5..19).find { |i| $available[i] != 1 }
Then once you have the index, have checked that it isn't nil, and stored it in $i, just $available[$i] = 1 to reserve the seat.
And an extra hint for free, this:
answer = STDIN.gets
answer.chop!
leaves a string in answer so answer == 1 will always be false.
References:
Enumerable#find
The problem seems to be here:
break if answer =~ /1|2/
This means "stop and leave the loop entirely if if we get a 1 or 2"
ie it means that none of your code that does seat-allocation gets executed if the person actually enters something valid (ie a 1 or 2).
After that comes the errors pointed out by #mu_is_too_short above.

Resources