Ruby, random number generator and if statement - ruby

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

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

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

elegant way to check if a string inputed by user is an integer in ruby?

I'm trying to validate that the input a user gives my program via gets is an integer. is_a?(Integer) does not work, as far as i can tell, because gets gets a string from the user, so it will always return false even if the user enters an valid integer (in string form). One would think I could simply use to_i on the input and be done with it, but that raises another issue - "75akjfas".to_i results in 75. So if I relied on to_i to solve my problems, anything starting with numbers will work.
How do I cleanly validate that the value is an integer only, and not a combination of numbers and letters? Or do I need to resort to regex for this?
print "Enter an integer (or try to sneak by something other): "
puts Integer(gets) rescue puts "Hey, that's not an integer!"
How about s.to_i.to_s == s? I'd prefer regex however.
Using regex you could do it like this:
class String
def integer?
!!(self =~ /^[-+]?[0-9]+$/)
end
end
You could use Integer() but you need to be careful with hex, binary, or octal input. http://ruby-doc.org/core-2.3.1/Kernel.html#method-i-Integer
def valid_integer?(string)
begin
!!Integer(string)
rescue ArgumentError
false
end
end
Check this code example for how to use the checked string input by the user
puts "Enter a number: "
user_input = gets.chomp
check = (user_input.to_i.to_s == user_input)
while (!check ) do
puts("Wrong Input, Pls, Enter a number: " )
user_input = gets.chomp
check = (user_input.to_i.to_s == user_input)
end
if user_input.to_i < 0
puts "Number is negative"
elsif user_input.to_i > 0
puts "Number is positve"
else
puts "Number is Zero"
end
Ruby can do it without esoteric solutions:
Integer is a integer
1970.is_a?Integer
true
String is not a integer
"1970".is_a?Integer
false
String to integer is a integer
"1970".to_i.is_a?Integer
true

Misbehaving Case Statement

I'm messing around in Ruby some more. I have a file containing a class with two methods and the following code:
if __FILE__ == $0
seq = NumericSequence.new
puts "\n1. Fibonacci Sequence"
puts "\n2. Pascal\'s Triangle"
puts "\nEnter your selection: "
choice = gets
puts "\nExcellent choice."
choice = case
when 1
puts "\n\nHow many fibonacci numbers would you like? "
limit = gets.to_i
seq.fibo(limit) { |x| puts "Fibonacci number: #{x}\n" }
when 2
puts "\n\nHow many rows of Pascal's Triangle would you like?"
n = gets.to_i
(0..n).each {|num| seq.pascal_triangle_row(num) \
{|row| puts "#{row} "}; puts "\n"}
end
end
How come if I run the code and supply option 2, it still runs the first case?
Your case syntax is wrong. Should be like this:
case choice
when '1'
some code
when '2'
some other code
end
Take a look here.
You also need to compare your variable against strings, as gets reads and returns user input as a string.
Your bug is this: choice = case should be case choice.
You're providing a case statement with no "default" object, so the first clause, when 1, always returns true.
Effectively, you've written: choice = if 1 then ... elsif 2 then ... end
And, as Mladen mentioned, compare strings to strings or convert to int: choice = gets.to_i

Resources