undefined method (NoMethodError) ruby - ruby

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("===============================================")

Related

Ruby beginner: code only repeats 2 times

Hey the code I created only repeats 2 times.
After I type the second time "y" for the "continue_question"-method the code only stops.
def greeting
puts "Hello! Please type your name: "
name = gets.chomp.capitalize
puts "It is nice to meet you #{name}. I am a simple calculator application."
puts "I can add, subtract, multiply, and divide."
end
greeting
def calculator
puts "First number: "
#n1 = gets.chomp.to_i
puts "Secons number: "
#n2 = gets.chomp.to_i
def calculation
puts "Type 1 to add, 2 to subtract, 3 to multiply, or 4 to divide two numbers: "
operation_selection = gets.chomp.to_i
if operation_selection == 1
#result = #n1 + #n2
elsif operation_selection == 2
#result = #n1 - #n2
elsif operation_selection == 3
#result = #n1 * #n2
elsif operation_selection == 4
#result = #n1 / #n2
else
puts "Something went wrong!"
calculation
end
end
calculation
puts "Your Result is #{#result}"
end
calculator
def continue_question
puts "Do you want to continue? (y/n)"
continue = gets.chomp.to_s
if continue == "y"
calculator
elsif continue == "n"
puts "Bye!"
else
puts "What?"
continue_question
end
end
continue_question
Your code does not repeat 2 times, it repeats once.
The reason is because in your continue_question method, you do not tell it to repeat again:
def continue_question
puts "Do you want to continue? (y/n)"
continue = gets.chomp.to_s
if continue == "y"
calculator # <-- This causes it it repeat ONCE!
elsif continue == "n"
puts "Bye!"
else
puts "What?"
continue_question
end
end
A quick fix is to re-call the continue_question method below that line, to recursively repeat itself:
def continue_question
puts "Do you want to continue? (y/n)"
continue = gets.chomp.to_s
if continue == "y"
calculator
continue_question # <-- Add this to repeat indefinitely
elsif continue == "n"
puts "Bye!"
else
puts "What?"
continue_question
end
end
The problem is that continue_question only executes once, at the end of your code, but you need to loop until user exits (i.e types n).
So simply add a loop inside continue_question, for example:
def continue_question
continue = "y"
until continue == "n" do
puts "Do you want to continue? (y/n)"
continue = gets.chomp.to_s
if continue == "y"
calculator
elsif continue == "n"
puts "Bye!"
else
puts "What?"
end
end
end
Hey the code I created only repeats 2 times.
I think you misunderstand the following:
if continue == "y"
calculator
elsif continue == "n"
puts "Bye!"
When you call the above function calculator, you are still executing the continue_question function. So when the calculator finishes executing, continue_question will finish as well and the program will stop. For the wanted result you can try using a loop.

Output Method Return Value to Variable? Ruby

Is there a way to store the output of a method in a variable in Ruby? For example, if I wanted to store the return value of display_results in a variable to be evaluated by win_counter is that possible? I want win_counter to increment every time display_results has a winner.
win_combos = [
['rock', 'scissors'],
['paper', 'rock'],
['scissors', 'paper'],
['rock', 'lizard'],
['lizard', 'spock'],
['spock', 'scissors'],
['scissors', 'lizard'],
['lizard', 'paper'],
['paper', 'spock'],
['spock', 'rock']
]
scores = { player: 0, computer: 0 }
def display_results(first, second, combos = [])
combos.each do |combo|
if combo == [first, second]
puts "Player won!"
break
elsif combo == [second, first]
puts "Computer won!"
break
end
end
if first == second
puts "It's a tie!"
end
end
def win_counter(player, computer, scores)
if display_results(player, computer)
scores[:player] = scores[:player] + 1
elsif display_results(computer, player)
scores[:computer] = scores[:computer] + 1
end
puts "players wins: #{scores[:player]}; computer wins: #{scores[:computer]}"
end
display_results('spock', 'rock', win_combos)
win_counter('spock', 'rock', scores)
All you need to do is set a variable equal to the method call. You could use:
if display_results(player, computer) == "Player won!"
However, it might be more useful to split the logic for printing the winner away from the logic for the actual game. In ruby methods that return booleans are stylized with a '?' i.e empty? display_results should only display the results of the game, you shouldn't use an if statement on it.

Ruby function to check if a number is divisible by five and is even

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

Need help validating if user input is a number

I have the following code:
def say(msg)
puts "=> #{msg}"
end
def do_math(num1, num2, operation)
case operation
when '+'
num1.to_i + num2.to_i
when '-'
num1.to_i - num2.to_i
when '*'
num1.to_i * num2.to_i
when '/'
num1.to_f / num2.to_f
end
end
say "Welcome to my calculator!"
run_calculator = 'yes'
while run_calculator == 'yes'
say "What's the first number?"
num1 = gets.chomp
say "What's the second number?"
num2 = gets.chomp
say "What would you like to do?"
say "Enter '+' for Addition, '-' for Subtraction, '*' for Multiplication, or '/' for Division"
operation = gets.chomp
if num2.to_f == 0 && operation == '/'
say "You cannot devide by 0, please enter another value!"
num2 = gets.chomp
else
result = do_math(num1, num2, operation)
end
say "#{num1} #{operation} #{num2} = #{result}"
say "Would you like to do another calculation? Yes / No?"
run_calculator = gets.chomp
if run_calculator.downcase == 'no'
say "Thanks for using my calculator!"
elsif run_calculator.downcase == 'yes'
run_calculator = 'yes'
else
until run_calculator.downcase == 'yes' || run_calculator.downcase == 'no'
say "Please enter yes or no!"
run_calculator = gets.chomp
end
end
end
I need it to take the num1 and num2 variables that the user inputs and validate that they are numbers and return a message if they aren't.
I would like to use a Regex, but I don't know if I should create a method for this or just wrap it in a loop.
The Integer method will raise an exception when the given string is not a valid number, whereas to_i will fail silently (which I think is not desired behavior):
begin
num = Integer gets.chomp
rescue ArgumentError
say "Invalid number!"
end
If you want a regex solution, this will also work (although I recommend the method above):
num = gets.chomp
unless num =~ /^\d+$/
say "Invalid number!"
end
You would often see each section written something like this:
ERR_MSG = "You must enter a non-negative integer"
def enter_non_negative_integer(instruction, error_msg)
loop do
puts instruction
str = gets.strip
return str.to_i if str =~ /^\d+$/
puts error_msg
end
end
x1 = enter_non_negative_integer("What's the first number?", ERR_MSG)
x2 = enter_non_negative_integer("What's the second number?", ERR_MSG)
Here's possible dialog:
What's the first number?
: cat
You must enter a non-negative integer
What's the first number?
: 4cat
You must enter a non-negative integer
What's the first number?
: 22
#=> 22
What's the second number?
: 51
#=> 51
x1 #=> 22
x2 #=> 51

Why does the else condition of my if-statement not work?

I wrote a tic-tac-toe program. The problem I am experiencing is that in my if statement, which allows the user enter his/her desired coordinate, my else condition is not working. The else condition is in place in case the user enters a coordinate not on the board.
This is my code:
class Game
def initialize
#board=Array.new
#board[1]="1 __|"
#board[2]="__"
#board[3]="|__"
#board[4]="\n2 __|"
#board[5]="__"
#board[6]="|__"
#board[7]="\n3 |"
#board[8]=" "
#board[9]="| "
#turn="o"
#win_status = false
end
def turn
#turn
end
def show_board
puts " 1 2 3"
#board.each do |i|
print i
end
puts ""
end
def set_turn #switches turns
if #turn == "x"
#turn = "o"
else #turn == "o"
#turn = "x"
end
end
def make_move
puts "Enter x coordinate"
x=gets.to_i
puts "Enter y coordinate"
y=gets.to_i
if y==1 && x==1
#board[1]="1 _"+#turn+"|"
elsif y==2 && x==1
#board[2]="_"+#turn
elsif y==3 && x==1
#board[3]="|_"+#turn
elsif y==1 && x==2
#board[4]="\n2 _"+#turn+"|"
elsif y==2 && x==2
#board[5]="_"+#turn
elsif y==3 && x==2
#board[6]="|_"+#turn
elsif y==1 && x==3
#board[7]="\n3 "+#turn+"|"
elsif y==2 && x==3
#board[8]=" "+#turn
elsif y==3 && x==3
#board[9]="| "+#turn+" \n"
else
"You entered an invalid coordinate"
end
end
def win_combo
return [[#board[1][4] + #board[2][1] + #board[3][2]], [#board[4][5] + #board[5][1] + #board[6][2]], [#board[7][5] + #board[8][1] + #board[9][2]],[#board[1][4] + #board[4][5] + #board[7][5]], [#board[2][1] + #board[5][1] + #board[8][1]], [#board[3][2] + #board[6][2] + #board[9][2]], [#board[1][4] + #board[5][1] + #board[9][2]], [#board[3][2] + #board[5][1] + #board[7][5]]]
end
def check_win
#if some row or column or diagonal is "xxx" or "ooo" then set #win_status = true
self.win_combo.each do |arr|
str = arr.join
if str == "xxx"
puts "X Wins!"
return true
elsif str == "ooo"
puts "O Wins!"
return true
end
end
return false
end
g = Game.new
while g.check_win != true
g.show_board
g.set_turn
g.make_move
end
end
You are just returning the string: "You entered an invalid coordinate".
I suspect that you want to display it using:
puts "You entered an invalid coordinate"
Otherwise it is passed as the result of g.make_move and then ignored.
I'm assuming you would like to print: "You entered an invalid coordinate" to the console in the event of an invalid x, y coordinate. You need to add a method to that statement like:
else
puts "You entered an invalid coordinate"
end
Or:
else
abort "You entered an invalid coordinate"
end
It looks you you forgot to use puts or print in front of your "You entered an invalid coordinate" string. As it is currently written it is returned from the method.
In Ruby, the return value of a method is the value returned by the last statement evaluated. For example, both of these methods will return the same value if x=3:
def square_example(x)
if x ==3
x_squared = 9
end
end
def square_example2(x)
if x == 3
x_squared = 9
end
return x_squared
end
For simplicity of testing you might try using explicit returns so that you can easily tell what it is you are returning from the method. Or (as a beginner with Ruby myself) you could add in a puts statement with each if/else result so that you can easily monitor the results of each move and then remove those puts lines when you know everything is working properly.
Looks like this is a misinterpretation of the site below, but if you're interested in the difference between 'and' and '&&' you should check out the comments below.
From: http://www.tutorialspoint.com/ruby/ruby_operators.htm
You will want to use "and" instead of "&&", an example:
if y==1 and x==1
# do move
elsif y==2 and x==1
# do move
.
.
.
else
"invalid coordinate"
end
The "&&" operator will check that the values on either side of it are nonzero. If they are both nonzero then it will return true. In your case it is doing the operation
false && false
Where false != 0, so it returns true.
Here is another discussion of this: http://archive.railsforum.com/viewtopic.php?id=27353

Resources