Until statement not working on simple code [closed] - ruby

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 6 years ago.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Improve this question
I'm trying to set up a pretty simple dice roll and response in the prompt and it's not working right. I wanted the loop to keep asking until the user inputs roll, Roll or ROLL.
def roll()
x = rand(5) + 1
y = rand(5) + 1
z = rand(5) + 1
puts "You rolled #{x},#{y},#{z}"
if x == y && y == z
puts "TRIPS! Trip #{x}s"
elsif x == y || y == z || x == z
puts "Pair!"
else
if x > y && x > z
puts "#{x} high"
end
if y > x && y > z
puts "#{z} high"
end
if z > x && z > y
puts "#{z} high"
end
end
end
puts "Type 'roll' when you're ready."
entry = gets.chomp
until entry == roll || Roll || ROLL
puts "Type 'roll' when you're ready."
entry = gets.chomp
end
roll()

# Remove these two lines and just use them in the while / until
# puts "Type 'roll' when you're ready"
# entry = gets.chomp
entry = ''
# Use String.downcase on entry because the user could type rOLL or RoLl
while entry.downcase != 'roll' # or you can use until entry.downcase == 'roll'
puts "Type 'roll' when you're ready."
entry = gets.chomp
end
You are comparing entry to values that do not exist. You need to compare to a string.
Roll by convention should be a class / model / object of some kind. For example
class Roll
# create roll
def initialize()
end
end
roll = Roll.new
# or for an existing class like Arrays
array = Array.new
ROLL by convention would be a previously defined constant.
ROLL = 7
# => 7
ROLL = 4
# => warning: already initialized constant ROLL

Here's an example of how you can do it in a more Ruby fashion that makes it more extensible.
Start with making your roll method focused on one very simple thing:
def roll(sides = 6, count = 3)
Array.new(count) { rand(sides) + 1 }
end
Note that rand(5) produces values in the range of 0..4, it never yields 5. The idea here is to return an array that's of arbitrary length, and by having exposed arguments with defaults you can re-purpose this method easily for other situations.
Then move all of the display logic to the main loop:
loop do
puts "Type 'roll' when you're ready."
entry = gets.chomp
case (entry.downcase)
when 'roll'
rolls = roll
puts "You rolled #{rolls.join(', ')}"
case (rolls.uniq.length)
when 1
puts "TRIPS! Trip #{rolls[0]}s"
when 2
puts "Pair!"
else
puts "#{rolls.max} high"
end
break
when 'quit'
break
end
end
Using an array structure instead of three arbitrary variables helps considerably when working with them in aggregate. You can see how things like uniq and max are effortless in this situation.

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

assigning a method result to a variable in ruby

I'm sure it would be hard to find an easier question, but I'm a complete newbie. I have searched extensively and for some reason can't find the answer to this. Here's my code:
puts "Enter F for Fahrenheit and C for Celsius."
x = gets.chomp.downcase
def ftoc(fahrenheit)
(fahrenheit.to_f - 32.0) * (5.0 / 9.0)
end
if x == "f"
puts "Enter your temp:"
temp = gets.chomp.to_i
ftoc temp
elsif x == "c"
puts "Enter your temp:"
temp = gets.chomp.to_i
ctof temp
else
puts "That does not compute."
end
I'm just trying to get the returned result of the method into a variable so I can use it elsewhere....
Remember that calls like ctof temp just initiate a method and then, as you're not putting the result anywhere, discard it immediately.
To clean up this code let's organize it better:
# Temperature conversion method
def ftoc(fahrenheit)
(fahrenheit.to_f - 32.0) * (5.0 / 9.0)
end
# User input method
def temperature_prompt!
puts "Enter F for Fahrenheit and C for Celsius."
x = gets.chomp.downcase
case (x)
when "f"
puts "Enter your temp:"
temp = gets.chomp.to_i
ftoc temp
when "c"
puts "Enter your temp:"
temp = gets.chomp.to_i
ctof temp
else
puts "That does not compute."
end
end
Now you can make use of the fact that in Ruby things like if and case actually return values. In this case it's the value of the last thing to execute in each block, so that result isn't discarded, it's just passed along:
temp = temperature_prompt!
If you enter an invalid value you get the result of puts which is conveniently nil.
Here's something to consider: Ruby is very good at parsing arbitrary text if you can describe the patterns. Here's a simple input routine:
def temperature_prompt!
puts "Enter degrees (e.g. 8F, 2C)"
case (input = gets.chomp.downcase)
when /(\d+)f/
ftoc $1
when /(\d+)c/
ctof $1
else
puts "That does not compute."
end
end
You could add to those patterns to allow things like -2C and 3.4°F if you wanted.

How to solve ruby string [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I'm new to ruby, and I'm trying to make a simple calculator in which a user types in a simple problem (such as addition or subtraction) and the answer is returned. The problem is when the user types in a question, the question itself is being returned instead of the answer to that question.
puts "How many Questions?"
questions = gets.chomp.to_i
questions.times do |problem|
puts "question: "
problem = gets.chomp
puts "answer: #{problem}"
end
Inside your loop, instead of:
problem = gets.chomp
puts "answer: #{problem}"
Try this:
problem = gets.chomp
solved_problem = eval(problem)
puts "answer : #{solved_problem}"
eval will take care of interpreting your string as a Ruby instruction. But it's very messy, because anyone could write any Ruby program in your input and eval will make it run, so it's not safe at all.
If you only want to take care of simple operations, you can use a regex first to check if the input string looks like what you want:
problem_is_ok = (problem =~ /^\d+ *[+-] *\d+$/)
This will be true if the string starts with a number, followed by 0 to many spaces, followed by either a + or - sign, followed by 0 or more spaces, followed by another number and nothing else. Then you raise an error if this is not true.
Your loop now look like this:
questions.times do |problem|
puts "question: "
problem = gets.chomp
problem_is_ok = (problem =~ /^\d+ *[+-] *\d+$/)
if problem_is_ok
puts "answer: #{eval(problem)}"
else
#I raise an error, but you might aswell just print it instead for your simple program
raise ArgumentError("Can't compute this")
end
end
Add and subtract can be simple ruby definitions
We pass in 5 and 1
The lower portion of the code is the clear user interface implementation
when we loop we do it 3 times
It outputs 3 options for the user to select from
We read in with chomp, standard in, the keyboard, chooses 1, 2, or 3
If elsif statements conditionally select for each case
Using string interpolation we render the variables a and b into a new string,
and run their respective methods (add or subtract)
Converting that methods integer output to a string, and concatenate it.
Outputting that to the users screen
The 3rd option does no calculation,
instead it prints to users screen a simple string
our else condition catches the case when people don't enter one of the choices of 1, 2 or 3
It tells you to correct your choice to the options provided
Hope this helps
#!/usr/bin/env ruby
questions = 3
a, b = 5, 1
def add(a,b)
a + b
end
def subtract(a,b)
a - b
end
questions.times do |questions|
puts "Please choose:
1. add
2. subtract
3. exit"
questions = gets.chomp
if questions == '1'
puts "#{a} + #{b} = " + add(a,b).to_s
elsif questions == '2'
puts "#{a} - #{b} = " + subtract(a,b).to_s
elsif questions == '3'
puts 'exiting, goodbye.'
exit
else
p 'please choose again'
end
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

Guessing Game Ruby

So i have been learning ruby as of late and i am working on this code for practice purposes but i cannot seems to be able to solve this problem any help would be appreciate it.
This is are the guidelines i am following:
clear the screen
greet the player
explain the rules of the game to the player
generate a random number between 0 and x (x being a variable that can be set to any integer)
allow the player n number of guesses (n being a variable)
keep track of the guess history
don't count repeated guesses against the player
congratulate the player when he/she guesses correctly
alert the player when there is only one guess remaining
print the guess history at the end of the game
count number of games won IN A ROW
count number of games won in total
congratulate the play on 3 games won IN A ROW
ask if the player wants to play again
thank the player for playing games if the number of games played is greater than 2
please keep in my that this is work in progress and i have not completed all the guideline, however my questions is with one particular part of it.
here is the code:
guess = Array.new
puts guess.class
def ask()
puts "Please answer in a 'y' or 'n' only!"
puts "Would like to play again?"
end
def guess_check_against()
g = guess.last
unless guess.include?(g) != guess
count+=1
else
puts "sorry you have guessed that number before, Guess Again: "
guess << gets.to_i
count+=1
end
end
puts "what is your name?"
user= gets.chomp
puts "Hello #{user}!!"
max_user_attempts = 4
#attempt_counter = 0
directions = "\nLets play a guessing game! You have
#{max_user_attempts.to_s} guesses before you lose."
print directions
g = guess.last
win = 0
count = 0
play = true
while play == true
puts "Please tell me the max value of the random number: "
max= gets.to_i
num= rand(max)
puts "Ok. The random number is generated between 1 and " + max.to_s + "."
puts "Make your guess: "
guess << gets.to_i
guess_check_against()
#attempt_counter+=1
while guess != num && play != false
if g > num && #attempt_counter < max_user_attempts
print "That's too high. Guess again: "
guess << gets.to_i
guess_check_against()
#attempt_counter+=1
elsif g < num && #attempt_counter < max_user_attempts
print "That's too low. Guess again: "
guess << gets.to_i
guess_check_against()
count+=1
#attempt_counter+=1
else
break
end
end
if #attempts_counter >= max_user_attemtps
puts "Sorry! you lost! Try Again"
break
else #attempts_counter <= max_user_attempts
puts "Correct! You guessed the answer in " + count.to_s + " tries!"
win+=1
end
if win >= 3
puts "Congratulation! you have #{win} number of games in a row"
ask()
answer = gets.chomp!
elsif win < 3
ask()
answer = gets.chomp!
else
break
end
if answer == 'n'
play = false
break
end
if answer == 'y'
play = true
count = 0
end
end
puts "Ok. Goodbye!!"
and here is the error i keep receiving when i try to run this program:
guessing_game.rb:12:in `guess_check_against': undefined local variable or method `guess' for main:Object (NameError)
from guessing_game.rb:45:in `<main>'
when i try to use irb to run the same scenario it works completely fine.
i can not figure out what i am doing wrong, please help!!
The method definition
def guess_check_against()
g = guess.last
...
end
has its own scope, and the local variable
guess = Array.new
that you defined outside of it, is not accessible inside the method definition. guess is not defined inside the method definition. You can change the code so that the method takes that as an argument, and it will become accessible.

Resources