Ruby factorial loop - ruby

Am I doing this wrong? I am trying to write a simple program to ask the user to enter a number until they wish to quit, but when I run the program it gives me an argument error stating bad value for range. what can I do to fix this problem?
var = true
while var == true
print "Enter a number ('Q/q to quit'): "
input = gets.chomp
if input == 'Q' || input == 'q'
var = false
puts "Goodbye!"
else
product = 1
for i in 1..input
product = product * i
end
end
end
puts "#{input}! is #{product}"

The problem is "input" is a string. You can't use it in your range. You need to convert it to a int.
change this:
for i in 1..input.to_i

Related

In Ruby, is there a way to have the user loop back through a conditional statement if they input the wrong range?

I wonder if there is a way to use the if-else statements to trigger a loop that has the user re-enter a valid input? I have tried using the While loop as that type of structure technically works, but I cannot get the correct implementation. As of now, I have used an if-else conditional to individually test for each number in the valid range, and if the user inputs any of those values, it moves on. The else statement tells the user it is incorrect, but I can't seem to figure out a way to loop the user back until they enter a valid number.
This is the code I am working with:
class Humanoid < Player
def play()
userinput = print 'Enter your move [1 - 5]: '
input = gets&.rstrip
if input == '5'
return input
elsif input == '4'
return input
elsif input == '3'
return input
elsif input == '2'
return input
elsif input == '1'
return input
else
return "That is not an option, choose again"
end
end
end
Is it possible to prompt the user to enter another number if it wasn't correct? I feel like it should be but I am currently stumped on what to do.
I would use a simple loop that runs forever unless you explicitly return (or break) from it:
class Humanoid < Player
def play()
loop do
print 'Enter your move [1 - 5]: '
input = gets.chomp
if %w[1 2 3 4 5].include?(input)
return input
else
puts "That is not an option, choose again"
end
end
end
end
Additionally, I cleaned up your conditions.
I would write it like this:’
loop do
userinput = print 'Enter your move [1 - 5]: '
input = gets&.rstrip
if input == '5'
return input
elsif input == '4'
return input
elsif input == '3'
return input
elsif input == '2'
return input
elsif input == '1'
return input
puts "That is not an option, choose again"
end
Basically, this just makes it repeat forever until a value is returned. If none is, then the issue is printed and it loops again.

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

Conversion to integer isn't executing?

i have this code :
#require_relative '../lib/hackex/net/typhoeus'
require_relative '../lib/hackex'
require 'rubygems'
require 'faker'
print "how many farms do you want : "
choice = gets.chomp
choice.to_i
check = choice.is_a?(Integer)
puts check
if choice > 250
puts "Error! you cannot make more than 250 farms at once"
elsif choice < 250
puts "Error! you have to make at least one farm..."
elsif choice.is_a?(Integer) == false
puts "Error, something went wrong !"
else
puts "making #{choice} acounts ! ! !"
cnt = 1
while choice>cnt
gen = Faker::Name.first_name + Faker::Name.last_name
path=("created1.txt")
email = gen+'#gmail.com'
password = Faker::Internet.password(8)
username = gen.to_s+'/>'
puts HackEx::Request.Do(http,HackEx::Request.CreateUser(username, email, password, facebook_id = nil))
cnt +=1
open(path, 'a') { |f|
f << "#{email};"
f << "#{password}"
f << "\n"
}
puts "Account created!"
puts "#{choice - cnt} accounts remaining!"
end
end
i am trying to determing if the choice is an integer... i did the .to_i on choice, but it returns false, meaning its not an integer, its a string, why isnt it switching ?
ps : i do not get any errors, and the rest of the code works fine, except for the if part
choice.to_i returns an integer, but does not change choice. If you want choice to be changed to the integral value of the old choice, you need to reassign it explicitly:
choice = choice.to_i
Quoting the doc of String::to_i, emphasis is mine
to_i(base=10) → integer
Returns the result of interpreting leading characters in str as an
integer base base (between 2 and 36).
So you have to assign the return to something, or itself:
choice = choice.to_i

Is it possible to execute a condition differently in a multiple condition while loop without creating an entire new while loop?

I don't really know how to word this short enough for me to google it.
But is it possible to execute a certain condition in a multiple condition while loop differently, without creating a whole entire while loop.
For example, Is it possible to do something like this
while num == "" || num == "0"
#ENTER CODE
Instead of doing this
while num == ""
print "YOU MUST ENTER A NUMBER!"
num = gets.chomp
end
while num == "0"
print "ZERO IS NOT A VALID NUMBER!"
num = gets.chomp
end
I want to know is it possible to do this, but make it look more visually appealing and concise.
This should do the trick, one loop and use conditionals for which error message to print.
while num == "" || num == "0"
print "YOU MUST ENTER A NUMBER!" if num == ""
print "ZERO IS NOT A VALID NUMBER!" if num == "0"
num = gets.chomp
end
You could write something like this:
while num.to_i.zero?
case number
when ''
print 'YOU MUST ENTER A NUMBER!'
when '0'
print 'ZERO IS NOT A VALID NUMBER!'
end
num = gets.chomp
end
This works, because to_i returns 0 for both the string "0" and nil.
Furthermore I would suggest to change the error message to simplify the code even more:
while num.to_i.zero?
print 'Please enter a number greater then zero'
num = gets.chomp
end

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

Resources