P is for Programming

Using Ruby Inject

August 31, 2010

As I mentioned in my last post, I’m running through the problems in Project Euler to learn Ruby.  It’s a really fun way of learning a new language while solving interesting problems.

While searching for some help on one of the question I managed to stumble across a very interesting post by Jay Fields that outlines the usage of the Enumerable#inject in Ruby.  I’m not going to explain what inject is or how it works – since he does that better than I could – but I am going to show you some scary-looking code that uses inject.  (The code isn’t scary, just that one line)

The code below is an attempted answer to Question 10 on Project Euler – Find the sum of all the primes below two million. (It turns out my solution is too slow – I had to think of a different algorithm) The interesting line is highlighted.  This is probably the most boring usage of inject you could possibly imagine, but I was still pretty happy that I managed to use it (hey, it’s my first time ok).

require 'test/unit'

class EulerProblem10 < Test::Unit::TestCase

    def test_sum_of_primes_below_10
        assert 17, sum_of_primes_below(10)
    end    

    def sum_of_primes_below n
        primes = [2, 3]
        while primes.last < n
            guess = primes.last + 1
            while not is_prime(guess)
                guess += 1
            end
            primes = primes << guess
        end

        primes[0..primes.length-2].inject { |result, element| result += element }
    end

    def is_prime n
        for d in 2..(n / 2)
            if (n % d) == 0
                return false
            end
        end

        true
    end    

end

Happy coding.

Tags: Ruby

  1. Wayne Conrad says:

    Looks good.

    An alternative to primes[0..primes.length-2] is primes[0...primes.length]. '…' in a range excludes the last element. Better yet, we can change the loop so that it does not put the extra prime onto the list:

    loop do

    break if guess >= n
    primes = primes << guess
    end

    Now for the good part. Now that the list of primes includes only the elements you want, you don't need to slice it:

    primes.inject { |result, element| result += element }

    Now for the really good part:

    primes.inject(:+)

  2. Jaco Pretorius says:

    primes.inject(:+)

    WOW! That's awesome! Thanks for the pointers on the '…' range bit as well.