Checking if content of an array is all integers [closed] - ruby

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 8 years ago.
Improve this question
I'm working on a sorting code. I would like to check if my array contains non integers. Here is my code:
array = Array.new
puts "Please enter your 3 digits."
3.times do
str = gets.chomp.to_i
array.push str.to_i
end
if array.is_a?(Numeric) == false
puts "Error, only use Integers please!"
else
print "Here are your sorted numbers: #{array.sort}"
end

You clearly can't gets.chomp.to_i (or the equivalent, gets.to_i), because that will only return integers. You therefore need to see if the string represents a number before adding it to the array.
You can do that with a regular expression or confirm that Kernel::Integer does not raise an exception (and catch it if it does).
A regular expression that would work is simply:
str =~ /^-?\d+$/
after
str = gets.chomp.strip
To use Kernel::Integer:
def integer?(str)
begin
Integer(str)
rescue ArgumentError
return false
end
str.to_i
end
For example,
integer?("-33") #=> -33
integer?("-x33") #=> false
integer?(" 33 ") #=> 33
integer?("33\n") #=> 33
The last two examples show that you can drop chomp.strip from gets.chomp.strip when using this approach.
If you wish to allow integers or floats, change the regular expression to:
/^-?\d+\.?\d*$/
or check to see that Kernel::Float raises an exception:
def float?(str)
begin
Float(str)
rescue ArgumentError
return false
end
str.to_f
end
float?("-33.4") #=> -33.4
float?("-33") #=> -33.0
float?("x33.4") #=> false
float?(" 33.4\n") #=> 33.4

With the code you have above your array is guaranteed to contain integers since you are converting your input to Integers using to_i:
array.push str.to_i
You are in fact doing it twice. When you read the string from STDIN and when you push it onto the array.
You need to check to see if the input is a string before you call to_i.
3.times do
str = gets.chomp
# code to verify if str is numeric.
array.push str
end
There are lots of ways to implement that code depending on what your requirements are. Integers only could be done like this:
unless str =~ /^\d+$/
puts "Error, only use Integers please!"
exit
end
The above would work for any positive integers, but not negative. It would also fail if you allowed decimals. But it gives you an idea. Search "ruby check if string is a number" and you'll find a lot more info.
Also note that the above fails as soon as it finds a non integer instead of waiting till after.

Related

Check if integer is positive in ruby

I'm trying to make users input a positive integer(>=1). If the user inputs a negative integer or 0, the program gonna notice and say you didn't put a valid integer, please try again. my program works so far until I try to input a string. My program break after I input a string. Does anybody know how to fix this?
I tried elsif !barsofsoap.match (/\A[-+]?[0-9]*.?[0-9]+\Z/)
puts "You didn't enter an integer, please put a positive integer", but it didn't work
loop do
puts "How many soaps are you looking to purchase? (Please put an integer)"
x = gets.chomp
barsofsoap = Integer(x) rescue false
if barsofsoap >= 1
break
else
puts "You didn't put an integer, please put an integer and try again."
end
end
I hope the program will not break if the user inputs a string.
The reason why your current code fails is because you use false as rescue value. You can't compare false >= 1. Sticking close to your original code you might wrap the comparison into a begin/end block.
loop do
puts "How many soaps are you looking to purchase? (Please put an integer)"
x = gets.chomp
begin
barsofsoap = Integer(x)
if barsofsoap >= 1
break
end
rescue ArgumentError => _error
puts "You didn't put an integer, please put an integer and try again."
end
end
Or simplifying the code:
loop do
puts "How many soaps are you looking to purchase? (Please put an integer)"
break if (barsofsoap = gets.to_i).positive?
puts "Invalid input. Provide a positive integer."
end
The above code doesn't detect if the input is a string or an integer. By replacing Integer(x) with x.to_i it would simply return 0 if invalid. Since you want the user to provide an positive integer it still requests them to provide a new integer.
nil.to_i #=> 0
''.to_i #=> 0
'asdf'.to_i #=> 0
'12.34'.to_i #=> 12
Like shown above the string '12.34' will produce the value 12. Depending on your requirements you might not want to use this value and instead mark it as invalid input. In this case you could use a regex to check the provided input.
loop do
puts "How many soaps are you looking to purchase? (Please put an integer)"
input = gets
break barsofsoap = input.to_i if input.match?(/\A[1-9]\d*\Z/)
puts "Invalid input. Provide a positive integer."
end
The regex /\A[1-9]\d*\Z/ will match the following:
\A Matches start of string.
[1-9] Matches one of the digits 1-9.
\d* Matches zero or more digits 0-9.
\Z Matches end of string. If the string ends with a newline, it matches just before the newline.
You try this: num.positive?
see here: https://ruby-doc.org/core-2.6/Numeric.html#method-i-positive-3F
Also you can try convert the text to an integer and validate by doing this:
num.is_a?(Integer)
https://ruby-doc.org/core-2.6/Object.html#method-i-is_a-3F
Or even better since input is always text, you can use a regex to make sure only numbers are entered: "12345" =~ /\A\d+\Z/
How about try this:
loop do
puts "How many soaps are you looking to purchase? (Please put an integer)"
barsofsoap = gets.chomp
if barsofsoap.match(/^[\d]+$/).nil?
puts "You didn't put an integer, please put an integer and try again."
elsif barsofsoap.to_i.positive?
break
else
puts "You didn't put an integer, please put an integer and try again."
end
end
Other option, using n.to_i.to_s == n to check the input is an Integer and moving the loop into a method:
def get_input_integer
loop do
puts "Enter a positive Integer"
n = gets.chomp
if n.to_i.to_s == n
return n.to_i if n.to_i.positive?
puts "It's not positive"
else
puts "It's not an integer"
end
end
end
x = get_input_integer

How do i print a string with repeated names followed by a number - Ruby? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
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.
Closed 6 years ago.
Improve this question
How do i print a name Ex. John1 and then print after John2, john3, john4, john5 and so one in an infinite number
I started using ruby today and I'm having some trouble figuring this out. I've searched some but can't find anything so how would I do this?
It's to mass produce accounts to the staff of a certain company and I found ruby to be the smartest to write it in and I will never use it again after this
Keep it simple.
puts (1..5).map { |n| "john#{n}" }
john1
john2
john3
john4
john5
The class Range includes the module Enumerable (as does the classes Array, Hash and others). By doing so, instances of Range (such as 1..5) gain the use of all of Enumerable's instance methods. One of Enumerable's instance methods is used here: Enumerable#map.
For printing a simple series like this:
n = 1
loop do
print 'john%d, ' % n
n += 1
end
That will never terminate, which makes it kind of silly. Maybe what you want is a bounded range:
list = (1..10).map do |n|
'john%d' % n
end.join(', ')
puts list
You can adjust the start and end values as necessary.
Perhaps use an enumerator here:
enum = Enumerator.new do |y|
i = 1
loop do
y << "John#{i}"
i += 1
end
end
enum.next #=> "John1"
enum.next #=> "John2"
enum.next #=> "John3"
Then use any one of the methods available to instances of Enumerator. Here we've used Enumerator#next to get the next "John" string.
One simple way is using a for loop. First declare an empty string variable that will hold our contents.
One important thing to consider is the index of the loop. If it's the last item, we do not want to add a separator like ", "
This is where the conditional comes into play. If the index is less than the last, we will add a comma and space, otherwise just the name.
Interpolation is done by wrapping a variable inside #{ and }
str = ""
for i in 1..5
str += i < 5 ? "john#{i}, " : "john#{i}"
end
Returns
"john1, john2, john3, john4, john5"

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

Making a sorted array of user's input

I'm learning Ruby with 'Learn to Program' by Chris Pine. On chapter 10 I should write a program where the user types as many words as he like and when he's done, he can just press Enter on an empty line and exit.
I came up with this:
puts "Type whatever you want!"
index = 0
word = ''
array = []
while word != nil
word << gets.chomp
array[index] = word
index = index + 1
end
puts ''
puts array.sort
But that doesn't work. What did I miss? Is there another way I could define word without having to repeat it?
The word will not have nil value. It will be an empty string. So you need to check for that:
while word != ""
# or even better
while !word.empty?
Also, you are adding everything to your word. You probably want to assign to it instead:
word = gets.chomp
Per author's comment:
begin
# your code here
end while !word.empty?
# OR more readable
begin
# your code here
end until word.empty?
It seems like there's a simpler solution, if I'm reading the question correctly.
You could do something like this:
user_input = gets.chomp.split(" ").sort
ex)
input: bananas clementine zebra tree house plane mine
output: ["bananas", "clementine", "house", "mine", "plane", "tree", "zebra"]
Here's a simple loop that you could do just for kicks:
arr = []
arr << $_.strip until gets =~ /^\s*$/
puts arr.sort
$_ is a special variable that evaluates to the last input read from STDIN. So basically this reads "Call gets and check if the input is just spaces. If it is then break out of the loop, otherwise append the last input with whitespace removed value onto the array and continue looping."
Or even more fun, a one liner:
puts [].tap {|arr| arr << $_.strip until gets =~ /^\s*$/}.sort
Basically same thing as above except using tap to initialize the variable.
To answer your questions:
Is there another way I could define word without having to repeat it?
Use side effects of assignment. In ruby when you assign a variable the return value of that assignment is the assigned variable, as in:
irb(main):001:0> (variable = 2) == 2
=> true
The idea would be to put the assignment in the your conditional. If I were to write something like this in a comprehensible loop, as opposed to those above, I'd write something like this:
arr = []
while !(word = gets.strip).empty?
arr << word
end
puts arr.sort
Using loop might simplify the code:
a = []
loop do
input = gets.chomp
if input.empty?
break
else
a << input
end
end
a.sort!
puts a

How should I setup this if and else statement? [duplicate]

This question already has answers here:
Array that alphabetizes and alternates between all caps
(5 answers)
Closed 7 years ago.
Without changing any of the other code- What can I put into my if else statement to make array 0, 2, 4 show up as all capital letters? I can't figure out how to assign this within the if and else statement.
test = []
puts "Please type 5 different words when you're ready-"
5.times do
test << gets.chomp
end
test.sort.each do |user|
if #what could I put in this statement for all capital letters on [0,2,4]?
user.upcase
else #.downcase isn't needed, if its simpler to remove it that is fine
user.downcase
end
end
I think what you need to do is change the each loop to each_with_index. The each_with_index loop should get what you need.
test.sort.each_with_index do |user, index|
if ([0,2,4]include? index)
user.upcase
else
user.downcase
end
end
If the array is going to expand, you could use the #even? method on the index as the check in the if statement like so.
test.sort.each_with_index do |user, index|
if (index.even?)
user.upcase
else
user.downcase
end
end
If you can't change the type of loop then you could use the #index method on the array, to tell you where the user is in the test array like so
test.sort.each do |user|
if ([0,2,4].include? (test.sort.index(user)))
user.upcase
else
user.downcase
end
end
Why without changing any of the other code? Just do this, no one will care:
puts "Please type 5 different words when you're ready-"
5.times.map { |i| i.even? ? gets.chomp.downcase : gets.chomp.upcase }
The times loop autoindexes for this reason, and the ternary operator (?:) is built for this case.

Resources