Ruby code efficiency - ruby

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

Related

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

How to determine whether input is empty or enter is pressed

I have a task to puts an infinite number of word, each in one line to array, and when enter is pressed on an empty line, puts these words in reverse order. How can I define when enter is pressed or empty line is input?
Code is here:
word = []
puts "Enter word"
add = 0
until add == ????
word.push gets.chomp
add = word.last
end
puts word.reverse
Here's a possible solution, with comments. I didn't see any useful role being played by your add variable, so I ignored it. I also believe in prompting the user regularly so they know the program is still engaged with them, so I moved the user-prompt inside the loop.
word = [] # Start with an empty array
# Use loop when the terminating condition isn't known at the beginning
# or end of the repetition, but rather it's determined in the middle
loop do
print 'Enter word: ' # I like to prompt the user each time.
response = gets.chomp # Read the response and clean it up.
break if response.empty? # No response? Time to bail out of the loop!
word << response # Still in the loop? Append the response to the array.
end
puts word.reverse # Now that we're out of the loop, reverse and print
You may or may not prefer to use strip rather than chomp. Strip would halt if the user input a line of whitespace.
Here, this is a modified version of your code and it works as requested.
word = []
puts "Enter word"
add = 0
while add != -1
ans = gets.chomp
word.push ans
if ans == ""
puts word.reverse
exit
end
add += 1
end
puts word.reverse
This is another version, using (as you did originally) the until loop.
word = []
puts "Enter word"
add = 0
until add == Float::INFINITY
ans = gets.chomp
word.push ans
if ans == ""
puts word.reverse
exit
end
add += 1
end
puts word.reverse

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

how to break a loop?

when 1
add(first_number, second_number)
begin
print "Calculate again? [y/n]: "
response = gets.chomp
if response.downcase =~ /[n]/
break
elsif response.downcase =~ /[^ny]/
puts "please input y or n"
else response.downcase =~ /[y]/
puts "yay"
end
end
EDIT
Profuse apologies. This is a changed version.
My question as it stands now is how do I keep repeating the question of 'please input y or n' when a user chooses to enter other than those characters?
the begin <code> end while <condition> is regretted by Ruby's author Matz. Instead, he suggests to use Kernel#loop,
e.g.
The while statement modifier normally checks the condition before entering the loop. But if the while statement modifier is on a begin ... end statement, then it loops at least once. Same with the until statement modifier.
Example of while
val = 0
begin
val += 1
puts val
end while val % 6 != 0
Example of until
val = 0
begin
val += 1
puts val
end until val % 6 == 0
As you wants to know about breaks..
Example of break unless
val = 0
loop do
val += 1
puts val
break unless val %6 != 0
end
Example of break if
val = 0
loop do
val += 1
puts val
break if val %6 == 0
end
Output:
Above all four of these examples print the numbers 1, 2, 3, 4, 5, 6.
I hope this answer makes you clear..
For your reference I have found very nice Example of Code about Table of Contents You can Execute(Run) that code here online and check the result. If my answer somehow helps you then you can accept as answered. :)
I would probably extract the confirmation into a method, something like:
def confirm(message)
loop do
print "#{message} [y/n]: "
case gets.chomp
when 'y', 'Y' then
return true
when 'n', 'N'
return false
else
puts 'please input y or n'
end
end
end
And use it like:
loop do
puts 'Calculating...'
sleep 5 # calculation
puts '42'
break unless confirm('Calculate again?')
end
Usage:
$ ruby test.rb
Calculating...
42
Calculate again? [y/n]: maybe
please input y or n
Calculate again? [y/n]: y
Calculating...
42
Calculate again? [y/n]: n
$
You should run your loopy method in a separate thread, and then
kill that thread when the user presses any key on the keyboard ...

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