C.Graco
C.Graco

Reputation: 59

Multiple conditions in a "While" loop Ruby

I'm creating an app that tells what month of the year each number from 1 to 12 represents, like 1 = January, 2 = February, etc. This is the initial code

print "Please, tell me the month's number!"
number = gets.chomp.to_i
while number > 12  do
    print "Please, re-type it again!"
    number = gets.chomp.to_i
end
case number
    when 1 then print "This is January!"
    when 2 then print "This is February!"
    when 3 then print "This is March!"
    when 4 then print "This is April!"
    when 5 then print "This is May!"
    when 6 then print "This is June!"
    when 7 then print "This is July!"
    when 8 then print "This is August!"
    when 9 then print "This is September!"
    when 10 then print "This is October!"
    when 11 then print "This is November!"
    when 12 then print "This is December!"
    else print "I can't undestand you, i'm sorry!"
end

Now, the basic logic is set. The only thing that I think is missing is the second condition in the while loop that defines that, if the input isn't an integer, I need to retype it. I'm trying to define the second condition in that while loop correctly, but no results so far. How can I do it?

How can I make the code better? And is the while loop in this context the right method for the job?

Upvotes: 0

Views: 8624

Answers (5)

checkmate101
checkmate101

Reputation: 99

A simple loop that you need:

until month_num > 0 && month_num < 13 do
 # prompt again
end

A more idiomatic way would be to use between? or include?

until month_num.between? (1, 12) do
  # prompt again
end

And instead of multiple when then, you could use a hash map from the Date module:- Date::MONTHNAMES[month_num]

Upvotes: 0

vgoff
vgoff

Reputation: 11313

print "Please, tell me the month's number!"
number = gets.to_i

You never need chomp if you are going to use to_i because the very nature of a number states that it will never have a line ending.

until number > 1 && number < 12  do

You do want the number to be inclusive of 1 to 12, right?

You could alternative do this,

until (1..12).include?(number) do

Or as @teenslag states,

until number.between?(1, 12) do

I think either reads easier, and between? method may be the better choice.

    print "Please, re-type it again!"
    number = gets.to_i
end

This can be very DRY, or using the built in Date object, as mentioned. But let's see what we can do with the code as you have it, in the same spirit:

case number
    when 1 then print "This is January!"
    when 2 then print "This is February!"
    when 3 then print "This is March!"
    when 4 then print "This is April!"
    when 5 then print "This is May!"
    when 6 then print "This is June!"
    when 7 then print "This is July!"
    when 8 then print "This is August!"
    when 9 then print "This is September!"
    when 10 then print "This is October!"
    when 11 then print "This is November!"
    when 12 then print "This is December!"
end 

turns to this:

answer = case number
         when 1
           "January"
         when 2
           "February"
         when 3
           "March"
         when 4
           "April"
         when 5
           "May"
         when 6
           "June"
         when 7
           "July"
         when 8
           "August"
         when 9
           "September"
         when 10
           "October"
         when 11
           "November"
         when 12
           "December"
         end
print "This is #{answer}!"

Though it would be nicer just using the Date class.

If that wasn't available for you, then perhaps I would consider using a Hash here instead. I will let you explore those options.

Or even an Array. Remembering that Array elements start at position 0:

print "Please, tell me the month's number!"
until (number = gets.to_i).between?(1,12) do
    print "Please, re-type it again!"
end
months = %w[January February March April May June July August September October November December]
puts "This is #{months[number - 1]}!"

Upvotes: 1

Dan Garman
Dan Garman

Reputation: 646

As the above posters have mentioned, this particular instance does not require a second condition. However, in the event you need a multiple condition while loop you would use the logical AND or the logical OR operator.

The logical AND operator is &&. The logical OR operator is ||. You would use && if both conditions need to be true to continue the loop. You'd use the || if one or the other would need to be true to continue the loop.

For example:

while number > 12 || number == 0 do
    stuff...
end

while number > 0 && number < 13 do
    stuff...
end

In the first snippet, you will enter the loop if the number entered is either above 12 OR equal to 0. In the second you will enter the loop if the number entered is greater than 0 AND less than 13. (Obviously, the second one would be exactly the opposite of what you were using the while loop for here, but is included for demonstration).

Upvotes: 0

emailnitram
emailnitram

Reputation: 141

Here is another way to make your code better:

require 'date'
print "Please, tell me the month's number! "
number = gets.to_i
until number.between?(1,12) do
  print "Please, re-type it again! "
  number = gets.to_i
end
month_name = Hash.new
(1..12).each do |month_num|
  month_name[month_num] = Date::MONTHNAMES[month_num]
end
print "This is #{month_name[number]}!"

As noted in other answers chomp is not necessary if using to_i because converting to an integer will take care of the new line. I am using number.between?(1,12) as suggested by @steenslag to check if the input is valid.

I tried a Hash approach instead of the case statement. A while loop is one way to do this but this is just one other way to get it done.

Upvotes: 2

davogones
davogones

Reputation: 7399

number will always be an integer because you converted it into an integer.

"foo".to_i
 => 0

You probably want to use a range instead.

until (1..12).include?(gets.chomp.to_i)
  print "Please, re-type it again!"
end

You can also DRY your code by using the built-in number to month conversion:

number = 4
Date::MONTHNAMES[number]
 => "April"

Upvotes: 0

Related Questions