Practice Solutions


The following are the solutions to the practice problems. You should earnestly attempt each practice problem before checking the solution. If you cannot reach the correct answer on your own try asking Google or referring back to the appropriate chapter from this text. Each problem should take no more than 10-15 minutes to solve for beginners.


Problem 1:

def get_count(string)
  string.scan(/[aeoui]/).count
end

puts get_count("today")
# => 2

Create a method that takes one argument. Pass the 'scan' method to the argument and search for the regular expression "any letter a - e - i - o - u". Chain the count method on the end to receive the number of vowels in the argument.


Problem 2:

def array_sort(array)
  array.sort_by {|x| x[-1]}
end

puts array_sort(['apple', 'cat', 'dog'])
# apple
# dog
# cat

Create a method that takes one argument and pass the sort_by_ _method to the argument. This method takes a block where we can specify how we want to sort the array. In the block we tell ruby that for a given word, "x", we want to sort the array by the last letter, x[-1]. Recall that Ruby uses zero-indexing, where the first item in an array is at position 0, the second at position 1, the third at position 2, and so on. The last item in an array of unknown length can be found at position -1, the second last item at position -2, and so on.


Problem 3:

def starts_with_vowel(array)
  array.select { |elem| elem[0] == elem[/[aeiou]/] }
end

puts starts_with_vowel(['apple', 'cat', 'dog'])
# => apple

Notice how we have been starting each solution the same way. We define a method with the def keyword and a descriptive name. Then we pass in an argument in parenthesis that we can refer to inside the method. The arguments so far have been "string" or "array", a clue as to what the method expects. However, any argument name such as "x" or "arr" would suffice. For problem 3, we use the select method on the array and specify the first letter (elem[0]) should be equal to any letter a - e - i - o - u.


Problem 4:

def word_count(file_path)
  file = File.open(file_path, 'r')
  array_of_words = []
  file.each_line {|line| array_of_words << line}
  array_of_words.first.split(' ').count
end

## words.txt ##
# There are seven words in this file.

puts word_count('words.txt.)
# => 7

To solve problem four we reach for the open method of the File class. The 'r' option opens the file in "read-only" mode. Next, we create an empty array to store all of the words from the file. So far, so simple. There are several ways to go about counting the number of words in a file. The method we've chosen appends each line of words to the array we created. Since all of the words from the file are now stored in our array we can find the total number by using the split method while attaching the count method. The split method tells ruby to separate the elements in the array by white spaces. Notice we explicitly specified spaces by passing the (' ') argument. However, this could have been omitted since splitting by white space is the default behavior of split. The count method, of course, counts all of the words.


Problem 5:

def special_chars(string)
  string =~ /\W/ ? true : false
end

puts special_chars('hell∞')
# => true

Here we are testing a string for special characters. There are multiple regular expressions to test for such a case. We've chosen to use the shorthand "\W". To test the method we pass in the word "hello" but replace the "o" with the infinity symbol. The result is true as we were expecting.


Problem 6:

def sort_values(array)
  array.sort { |a, b| b<=> b}
end

arr = [{'price': 1}, {'price': 2}, {'price': 3}]

puts sort_values(arr)

# {:price=>1}
# {:price=>2}
# {:price=>3}

This problem demonstrates a certain utility that's important to understand. Data is usually passed around in the form of arrays. The type of data inside the array most often takes the form of objects. If we called sort on the array of objects we would get an error back because we haven't told ruby how we want to sort the objects. Sorting numbers and letters is straight forward and requires no instruction. However, to sort an object, a key:value pair, we must explicitly tell ruby what to do. We do this by first defining an object as " |a, b| ". This tells ruby that the 'a' is representing the key and 'b' is representing the value. Finally, we use the "spaceship" operator in the form of " b<=>b " to tell ruby we want it to sort the objects by comparing the values. If you are not familiar with the spaceship operator read the documentation on sorting Enumerables.


Problem 7:

arr = %w(bob level noon rotator madam 9 stats elite fortress)

def palindromes(array)
  array.select {|word| word if word == word.reverse}.length
end

puts palindromes(arr)
# => 7

As you can see, these problems are not difficult to solve. Although they may seem intimidating at first, there is a logical pattern to finding the solution. It's a combination of knowing the right methods to reach for, in this case select, then explicitly telling ruby how we want it to respond. We've been doing this the same way nearly every time. Within our code block we define a variable between pipes | example | and then use that variable to define some requirement. In problem number 7, we are selecting the words only if "word" is equal to "word" when it is reversed. Then simply chain the length method to the end so ruby returns a number. Ruby is known for being able to solve problems in a single line of code, colloquially known as a "one-liner". Solving a problem in a single line of code isn't always possible but it's a good goal to reach for.


Problem 8:

require 'httparty'
url = 'http://jsonplaceholder.typicode.com/posts/1'
post = HTTParty.get(url)
puts post['title']
# => "sunt aut facere repellat provident occaecati excepturi optio reprehenderit"

Ruby has about two dozen libraries for working with HTTP. Some of the more popular choices are 'net/http', 'HTTParty', 'open-uri', and 'rest-client'. Each library may have subtle differences for retrieving data. For example, 'httparty' uses HTTParty.get(url) while 'open-uri' uses a simpler open(url). Otherwise the process is similar across the board. There may be instances where you'll need to call JSON.parse(the-result) before being able to work with the data, depending on the library you're working with. If this is the case, the recommended practice is to model the data as an OpenStruct. This transforms the data into an object where the values can be reached via dot notation, i.e. "post.title" would produce the title of the post. To work with OpenStruct the library must first be imported. See this sample code here:

require 'open-uri'
require 'ostruct'                                                                     **
class MarketsController < ApplicationController
  def index
    markets = open('https://bittrex.com/api/v1.1/' + '/public/getmarkets')
    raw_markets = JSON.parse(markets.to_json)
    @markets = raw_markets.map do |market|
      JSON.parse(market, object_class: OpenStruct)                                    **
    end
  end
end

The stared lines demonstrate how to make use of the OpenStruct. By structuring the code in such a way the values for the @markets properties can be reached by passing the keys to @markets. For example, the first key, "status", returns a boolean depending on the success or failure of the api call. We can now check the status with @markets.status.


Problem 9:

 def email_domain(email)
    email.gsub(/.+@([^.]+).+/, '\1')
 end

puts email_domain('[email protected]')
# => aol

To solve problem 9 we combine the gsub method with what we know about regular expressions. A good resource for editing and testing regular expressions is Rubular. For more information on the gsub method check out the Ruby docs, which detail the different use cases and provide multiple examples.

Problem 10:

There are multiple ways to solve this problem. Here is a first attempt:

 range = 1..100
 range.each do |n| 
 Fizz = n % 3 == 0
 Buzz = n % 5 == 0
 FizzBuzz = n % 3 == 0 && n % 5 == 0
  puts "FizzBuzz" if FizzBuzz
  puts "Fizz" if Fizz
  puts "Buzz" if Buzz
  puts n if !FizzBuzz && !Fizz && !Buzz
  end

 # Sample output

=begin
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
Fizz
Buzz
16
17
Fizz
19
Buzz
Fizz
=end

This first attempt is rather clunky. The repetitiveness indicates poor style but it gets the job done. I define a range of numbers 1-100 and use the each method to iterate over each number. I then declare the variables I'll be working with, "Fizz", "Buzz", and "FizzBuzz" as multiples of 3, 5, and 15 respectively. Finally, I use puts to print out the range with the necessary variable replacements. This code still needs to be DRYed up (Don't Repeat Yourself). On a second attempt, we can reduce the number of lines and make a call to puts just once:

   (1..100).each{|n|
      x = ''
      x += 'Fizz' if n%3==0
      x += 'Buzz' if n%5==0
      puts(x.empty? ? n : x);
    }
    # Output remains the same

This solution is a bit more clever. By setting 'x' to an empty variable and appending "Fizz" and "Buzz" appropriately we can use a single puts call with a ternary statement. During an interview you may have opportunities to improve upon your responses. In such cases, it's a good idea to write terse, readable code. Getting the correct solution is great. Getting the correct solution and writing high quality code puts you in a different league.


Don't stop here!

My second Ruby book will be released soon. I'll post updates on Learn2Code. The best way to get better at coding is by creating real applications. Don't be afraid to make mistakes. Read documentation and take notes if you don't understand something. Check out the free courses at Learn2Code and continue to develop your programming skills. I constantly hire developers that have completed our free courses, they are worth checking out. You can find my video posts on YouTube and of course feel free to reach out to me anytime at [email protected].

results matching ""

    No results matching ""