Daniel Dyba

Self-directed learning happens here

Ruby Monk Problem - Capitalizing an Array With Names (Revisited)

| Comments

Another Look

This is a follow up to my previous blog post on the Ruby Monk problem. The challenge with which I ended that post was to solve the problem with the constraint of using the inject method. Here’s a solution that meets that challenge:

1
2
3
["emperor", "john", "abraham", "norton"].map(&:capitalize).inject do |full_name, name|
  "#{full_name} #{name}"
end

Instead of initializing the inject method with an empty string, I used the map method to apply the capitalize method on each of the elements in the array. Once I have done that, then using method chaining, I can start combining each element in the array in a cumulative manner with the inject method.

Let’s Race

Here’s an interesting question: If I had several thousands elements in the array, which solution would be better in terms of performance? It would probably be more efficient to use the hack in the previous post. In this solution, I am iterating through the array twice: once using the map method and a second time using the inject method.

I use Benchmark to give me an idea of what performance looks like between the two solutions.

Benchmarking the new solution
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
require 'benchmark'

names = []

10000.times do
  names << "emperor".split(//).shuffle.join
end

Benchmark.bm do |trial|
  trial.report("Map & inject:             ") do
    names.map(&:capitalize).inject do |full_name, name|
      "#{full_name} #{name}"
    end
  end
  trial.report("Inject with initial value:") do
    names.inject('') do |full_name, name|
      "#{full_name} #{name.capitalize}".strip
    end
  end
end

Double-take

Take a look at these results:

Benchmark Results
1
2
3
                            user     system      total        real
Map and inject:             0.310000   0.100000   0.410000 (  0.399476)
Inject with initial value:  0.500000   0.190000   0.690000 (  0.691769)

The new solution is 40% faster than the solution in my previous post! This was not what I expected at all! It seems counter-intuitive that iterating through an array twice is faster than iterating through it once.

Final Note

Yup, I’m guilty of having relied too readily on my assumptions. This will serve as a reminder to keep asking questions that challenge my thinking. What may seem obvious may not be so.

Comments