RubyLearning

Helping Ruby Programmers become Awesome!

Course Ruby Exercises

By Satish Talim

Here are the solutions to all the exercises in the Free Online Ruby Programming Course. These solutions have been picked up from the participants' code posted in the relevant forums.

Week 1

L1E1: This is a sample question from the "Ruby Association Certified Ruby Programmer" examination. Thanks to Satoshi Asakawa for the Japanese to English translation.

Select all correct answers which outputs Error message.

Answers:

  1. 2 + 8
  2. 3 * 10
  3. 4 ** 10
  4. "abcde" * 3
  5. "abcde" + 1
  6. "abcde" + "fghij"

ANS: 5

L1E2: Before executing the code given below, guess the results. Next, execute the code. Did you get it right? If you did not get it right, can you think of why?

Goal: Understanding operator precedence and association.

y = false
z = true
x = y or z
puts x
(x = y) or z
puts x
x = (y or z)
puts x

ANS: In irb:
x = false or true
Now, = has a higher precedence than or and hence it's like:
(x = false) or true
ie.
false or true

Now, for or if the first argument is false it returns the value of the next argument ie. it returns the value true in this example.
In SciTE, the program is:
x = false or true
puts x

as before it's like:
(x = false) or true
ie. x is assigned the value false but the value of the above expression is true which is not assigned to any variable and hence is lost.
Hence puts x prints false.

L1E3: Read the sprintf documentation and the % documentation in the String class and figure out the output being printed by this Ruby code

Goal: To realize that the Ruby documentation is at times incomplete or not clear.

puts "%05d" % 123

ANS: There is an operator form of the sprintf method: simply use a % operator between a format string and the arguments to be interpolated into it:

"%05d" % 123

L1E4: Write a Ruby program that displays how old I am, if I am 979000000 seconds old. Display the result as a floating point (decimal) number to two decimal places (for example, 17.23).

Note: To format the output to say 2 decimal places, we can use the Kernel's format method. For example, if x = 45.5678 then format("%.2f", x) will return the string 45.57

ANS: The code is:

puts 'You are ' + format("%.2f", (979000000/60.0/60.0/24.0/365.0)) + ' years old.'

L1E5: Write a Ruby program that tells you how many minutes there are in a year (do not bother right now about leap years etc.).

ANS: The code is:

puts 'There are %d minutes in a year' % (60*24*365)

Week 2

L2E1: The following program prints the value of the variable. Why? Try to find the answer in the Programming Ruby book.

my_string = 'Hello Ruby World'
def my_string
 'Hello World'
end
puts my_string

ANS: Local variables have the quality of barewords; they must start with either a lowercase letter or the underscore character (_), and they must consist entirely of letters, numbers, and underscores. Remember, local variable references look just like method invocation expressions. Method calls can be barewords too. When Ruby sees a bareword, it interprets it as one of three things: a local variable, a keyword, or a method call.

  • If there's an equal sign (=) to the right of the bareword, it's a local variable undergoing an assignment.
  • If the bareword is a keyword, it's a keyword (Ruby has an internal list of these and recognizes them).
  • Otherwise, the bareword is assumed to be a method call.

L2E2: Write a method called convert that takes one argument which is a temperature in degrees Fahrenheit. This method should return the temperature in degrees Celsius.

ANS: The code is:

def convert (f)
  (( f - 32.0 ) / 9.0 ) * 5.0
end
puts "The temperature in Celcius = " + format("%.2f", convert(75.0))

L2E3: Write a Ruby program that asks for a temperature in degrees Fahrenheit. The program should display the temperature in degrees Celsius to 2 decimal places. To format the output to say 2 decimal places, we can use the Kernel's format method. For example, if x = 45.5678 then format("%.2f", x) will return the string 45.57. Another way is to use the round function as follows: puts (x*100).round/100.0

ANS: The code is:

# p006ftoc.rb
puts 'Enter temperature in Fahrenheit: '
STDOUT.flush
temp_in_fahrenheit = gets.chomp
temp_in_celsius = (((temp_in_fahrenheit.to_f - 32.0) / 9.0) * 5.0)
puts 'Temperature ' + temp_in_fahrenheit + ' degree Fahrenheit = ' + format("%.2f", temp_in_celsius) + ' degree Celsius'

Week 3

L3E1: Write a program that processes the string s = "Welcome to the forum.\nHere you can learn Ruby.\nAlong with other members.\n" a line at a time, using all that we have learned so far. The expected output is:

>ruby tmp.rb
Line 1: Welcome to the forum.
Line 2: Here you can learn Ruby.
Line 3: Along with other members.
>Exit code: 0

ANS: The code is:

s = "Welcome to the forum.\nHere you can learn Ruby.\nAlong with other members.\n"
i = 0
s.each_line { | l | print "Line " + (i += 1).to_s + ": "; print l }

L3E2: Run the following two programs and try and understand the difference in the outputs of the two programs.

The program:

def mtdarry
 10.times do |num|
 puts num
 end
end

mtdarry

and the program:

def mtdarry
 10.times do |num|
 puts num
 end
end

puts mtdarry

ANS: Case a. When you call the method by saying:
mtdarry
The times method iterates 10 times from 0 to (10-1) returning an int. Remember the value of the iterator num has now become 10. The displayed values are 0 to 9.

Case b. When you call the method by saying:
puts mtdarry
As in Case a, 0 to 9 are printed (using the puts inside the method) and the value of num is now 10. Methods return the value of the last executable statement. In the block, the value being returned is the value of num. When we call by: puts mtdarry, we are actually printing the value of num which became 10 inside the method.

L3E3: Write a Ruby program that asks for a year and then tells the user whether the year entered by him/her is a leap year or not.

ANS: The code is:

# p016leapyear.rb
=begin
Program to determine if a year is a leap year.

To determine if a year is a leap year, follow these steps:
1.   If the year is evenly divisible by 4, go to step 2. Otherwise, go to step 5.
2.   If the year is evenly divisible by 100, go to step 3. Otherwise, go to step 4.
3.   If the year is evenly divisible by 400, go to step 4. Otherwise, go to step 5.
4.   The year is a leap year (it has 366 days).
5.   The year is not a leap year (it has 365 days).

The above logic is combined into a single if check below
=end

# Get the input and determine if it is a leap year
puts "Enter the year: "
STDOUT.flush
input_year = gets.to_i
if ((input_year % 4 == 0) && (input_year % 100 > 0)) || (input_year % 400 == 0)
  puts "Year #{input_year} is a leap year"
else
  puts "Year #{input_year} is not a leap year"
end

This page contains selected exercises from the Ruby course. More exercises and their solutions are available in the complete tutorial.