# Getting Started with Ruby, III: Numbers and Logic

Ruby

Share:

#### Free JavaScript Book! Write powerful, clean and maintainable JavaScript.

RRP \$11.95

The last part of this series looked at strings and their methods, along with storing information as variables. We also wrote a Greeter program and Madlibs program, making web versions of them both using Sinatra. In this post, the focus is how to use numbers in Ruby and create logical statements.

Remember, if you want to follow along and do the examples, fire up `irb` from your command prompt.

## Time for Some Sums!

``````4 + 5
=> 9``````

4 and 5 are both objects and + is actually a method. We saw in the previous post how to call a method using the dot syntax and you can do the same with the `+` method:

``4.+(5)``

This is an example of adding arguments to a method. `4` is the object calling the `+` method and `5` is the argument. Ruby lets us write this in a more natural way (like writing out arithmetic). This is known as syntactic sugar, so `4 + 5` is seen as being equivalent to `4.+(5)`.

We can do lots of different arithmetic in a similar way:

``````10 - 4
=> 6
4 * 8
=> 32
9 / 2
=> 4``````

… Hang on! That last sum was incorrect. This is because 9 and 2 are both Integers. This means that the solution to 9/2 will only give you the integer part of the answer. To get the correct answer, we need to use a different type of number called a Float (because they use floating point decimals). To use Floats instead of Integers, just write 9 as 9.0 instead (this is known as a Float literal)

``````> 9.0/2
=> 4.5``````

That’s better!

Ruby gives us methods to find out if a number is odd or even:

``````> 4.odd?
=> false
> 5.odd?
=> true``````

In the last post we learned about ‘bang methods’. The `odd?` and `even?` methods are examples of boolean methods. These are methods that only return the result of `true` or `false`. They usually have a question mark (‘?’) character on the end of the method.

Ruby can also do some quite cool mathematical stuff, like finding the greatest commond divisor of two numbers using the `gcd` method. One number calls the method (12 in the example below) and the other number is the argument of the method (20 in the example below):

``````> 12.gcd(20)
=> 20``````

There is also a `lcm` method that finds the lowest common multiple of two numbers:

``````> 15.lcm(20)
=> 60``````

One of my favorite methods is the `times` method, shown in the example below:

``````> 5.times do
>  puts "Hello!"
> end
Hello!
Hello!
Hello!
Hello!
Hello!``````

I love how it encapsulates the readability of the Ruby programming language. It really does do what it says on the tin and reads almost like an English sentence. By the way, the bit of code between the `do` and `end` statements is called a block and we’re going to be covering much more about them in future posts.

One last `Integer` method that we’re going to look at is the `to_s` method, which stands for ‘to string’. It takes an integer and converts it into a string representation of that integer, for example:

``````> 7.to_s
=> "7"``````

This allows you to treat the number like a string. There is also an equivalent method for strings called `to_i` which changes a string into an integer:

``````"42".to_i
=> 42``````

You have to be careful with this as the string has to have some numbers at the beginning, otherwise it will return `0` (You can see more here).

## Generating Random Numbers

It’s often useful to generate a random number when programming. This is easily done in Ruby using the `rand` method. This will generate a floating point number between 0 and 1.0, like so:

``````> rand
=> 0.29635454177765397``````

If you provide an integer argument, then it will generate a random integer between 0 and up to, but not including the argument. For example:

``````> rand(6)
=> 2``````

The above code will generate a random number from 0 – 5. We can use this (and a bit of the arithmetic we learnt earlier to mimic the rolling of a die:

``````> rand(5) + 1
=> 4``````

Check out this very in-depth post from Robert Qualls on randoms and Ruby for more info.

## Logic

We can create logical statements in Ruby using the `if` and `then` statement. For example, we could play a game of trying to roll a 6 on a die:

``````number = rand(5) + 1
if  number == 6 then puts "Congratulations, you rolled a six!" end``````

Most of this is quite easy to figure out, but there are a few gotchas. First of all, notice the difference between `=` and `==`. In the first case, we use `=` for assignment, that is setting a variable, ‘number’ in this case, equal to a value, a random number from 1 to 6. In the second case, we are using `==` to test equality. In the example, we are testing if the value of number is equal to 6. Be careful not to confuse these because writing this:

``if  number = 6 then puts "Congratulations, you rolled a six!" end``

actually sets the value of number to 6 and therefore will always be true!

There is also an `else` statement:

``````number = rand(5) + 1
if number.odd?
puts "You rolled an odd number"
else
puts "You rolled an even number"
end``````

Notice that you don’t actually have to use the `then` statement. We can also nest lots of statements using the `elsif` statement (not the spelling!):

``````number = rand(5) + 1
if number == 1
puts "You rolled a 1"
elsif number == 2
puts "You rolled a 2"
elsif number == 3
puts "You rolled a 3"
elsif number == 4
puts "You rolled a 4"
elsif number == 5
puts "You rolled a 5"
else
puts "You rolled a 6"
end``````

## Guess My Number Program

Now that we’ve learned a little bit about how numbers work, we’re going to write a short program that invites the user to guess a randomly chosen integer from 1 to 100. Save the following code in a file called ‘guessmynumber.rb’:

``````number = rand(100) + 1
puts "I'm thinking of a number between 1 and 100, try and guess what it is"
guess = gets.to_i
attempts = 1
until guess == number do
if guess < number then puts "Too small, try again"
elsif guess > number then puts "Too big, try again"
end
guess = gets.to_i
attempts += 1
end
puts "Well done, you guessed my number in #{attempts} attempt#{'s' if attempts > 1}!"``````

First we set a variable called `number`, which is the random number between 1 and 100 that is to be guessed. We use the `rand` method with an argument of 100 and then add 1 to set this.

After this, the `puts` method is used to print a string explaining what the player has to do.
Then the `gets` method gets a guess from the player, which is stored in a variable called `guess`. Any input from the user is stored as a string (even if you enter a number), so we need to use the `to_i` method to ensure that the value is treated as an integer.
Next, set the number of attempts to 1 using the variable `attempts`. This will be used to keep track of how many attempts the user has before guessing correctly.
Then, there is the statement `until guess == number do`. This is a nice bit of Ruby that says: Until the guess is equal to the number, do the following. It’s an example of a loop that we’ll be looking at in more detail in the next part of the series.

After the `do` statement, we have another example of a block of code. This is what is carried out until the user guesses the right number.

We use the `if` and `elsif` statements to check if the guess is lower or higher than the number and then give some appropriate feedback. After which, take another guess and increase the number of attempts by 1. This is done using the statement `attempts += 1`, which is shorthand for writing `attempts = attempts + 1`.

Once the number is guessed correctly, the program breaks out of the loop and displays a message. The interpolation trick we learned in the last post is used to insert the `attempts` variable into the string. Notice that we have a neat way of using the `if` statement to pluralize the number of guesses if it’s more than one.

## Guess My Number on the Web

As usual in this series, we’re going to finish off by putting our program on the web using Sinatra. For this program we will need to keep note of the number after each request. The HTTP protocol that the web uses is stateless, which means that information isn’t stored between requests.

One way to get around this is to use sessions. This is easy to do in Sinatra – you just need to enable them. Create a file called ‘webguessthe_number.rb’ and add the following lines:

``````require 'sinatra'

enable :sessions``````

This requires the sinatra gem and also enables sessions. Sessions use cookies to store the information. Be aware that these are not secure and can be intercepted and decrypted. It’s not so much of a problem in the case of this game, but keep this in mind if you ever plan to store sensitive information.

Next we want to set the game up, we’ll start by creating a route handler for the root URL (found at http://localhost:4567) when a user request the web page.

``````get '/' do
@message = "I'm thinking of a number between 1 and 100, try and guess what it is"
session[:number] = rand(100) + 1
session[:attempts] = 0
erb :guess
end``````

First of all, set an instance variable called `@message`. Instance variables always start with a `@` symbol and they are available in the view associated with the route handler. At the end of the route handler we call the view `guess` using ERB. In the view, we will be able to refer to the `@message` variable. Also, we set the number and attempts variables in this route handler.

As mentioned earlier, we use sessions for this, otherwise the information will be lost after each request. This is done by using a hash to store the information, so `session[:number]` holds the value of the number and `session[:attempts]` holds the value of the number of attempts.

We need some HTML code that we’ll write using ERB, the following code goes at the end of the file:

``````__END__

@@guess
<!doctype html>
<html>
<title>Guess the Number</title>
<body>

<p><%= @message %></p>
<form method="POST" action="/">
<input name="number">
<input type="submit" value="Guess">
</form>
</body>
</html>``````

This is a basic web page that contains a form for submitting the guess. The form will be posted using the HTTP POST method and we also need to provide the route where it will be posted. In this case, we are doing what is called a postback when we use the same URL that the form is located on (the root of the site ‘/’ in this case). Notice that the `name` attribute is `number` as we’ll need this to grab the value of it when the form is posted.

We need to create a route handler for when this happens. Because the form is POSTed, we will use the post method for our route handler with the route that was specified in the form’s action attribute. Place the following code after the other route handler (but before the ERB code):

``````post '/' do
number = session[:number]
guess = params[:number].to_i
session[:attempts] += 1
redirect to('/success') if guess == number
if guess < number then @message = "Too small, try again"
elsif guess > number then @message = "Too big, try again"
end
erb :guess
end``````

Here we retrieve the number that was saved in the session hash, then grab the guess from the form. All values submitted by a form are strings, so we need to use the `to_i` method to convert it to an integer. We also increase the number of guesses (also stored in the session hash) by one.

Next, we use some `if` logic to redirect to a success page if the guess is equal to the number. Notice that this is written the other way round to the examples given above (the `if` statement comes first), which has the effect of making it more readable.

If the user isn’t redirected, then their guess must have been wrong, so we use some `if` and `elsif` logic to test if the guess is too big or too small and update the `@message` instance variable with an appropriate message. We finsih by displaying the `guess` view in ERB again so the user can provide another guess.

The paragraph that contains the `@message` variable will now display a different message depending on the guess, even though we are using the same view.

All that is left to do is create a success route handler. This goes after the last route handler:

``````get '/success' do
attempts = session[:attempts]
"Well done, you guessed my number in #{attempts} attempt#{'s' if attempts > 1}!"
end``````

This simply retrieves the number of guesses from the session hash then displays a congratulatory message that informs the user of how many attempts it took.

Have a go at playing the game by entering `ruby web_guess_the_number` in a terminal to start the server and then visiting http://localhost:4567 in your browser.

## That’s All Folks

In this post, we’ve introduced Integers and Floats and looked at some of their methods. We’ve also looked at how to construct a logical statement using `if`, `then`, `else` and `elsif` statements. We put all this together to create a “Guess the Number” program that we put on the web using sessions to store the information. In the next part of the series, we’re going to look at containers such as arrays and hashes and how to perform loops. In the meantime, have a play around with what we’ve covered so far and be sure to leave any questions or comments below. ### Darren Jones

Daz has been programming and building websites since the start of the millennium. He enjoys using Ruby and JavaScript and loves them both in their own special ways. He is the author of JavaScript: Novice to Ninja and Jump Start Sinatra. He also produced the 'Getting Started With Ruby' video tutorials for SitePoint and has written a number articles for SitePoint’s website. He was born in the city of Manchester and still lives there, where he teaches mathematics and enjoys playing water polo.

#### New books out now!  