Thursday, May 5, 2011

01 Kata [ruby] - sum of multiples of 3 or 5 less than 1000

Lets take a look at the ruby solution now.

class FirstKata
  def sum()
    sum = 0

    1000.to_i.times {
        |i| sum += i if (i % 3 == 0 || i % 5 == 0)
    }

    sum
  end
end

class FirstKataTest < Test::Unit::TestCase
  def test_sim
    assert_equal(233168, FirstKata.new.sum)
  end
end

This is the very same solution of the first one in java except that this one is in ruby.
So, lets make it a little bit more generic adding a parameter to the sum method.

class FirstKata
  def sum(upper_limit)
    sum = 0

    upper_limit.to_i.times {
        |i| sum += i if (i % 3 == 0 || i % 5 == 0)
    }

    sum
  end
end

class FirstKataTest < Test::Unit::TestCase
  def test_sum
    assert_equal(23, FirstKata.new.sum(10))
    assert_equal(233168, FirstKata.new.sum(1000))
  end
end

Lets make it even more generic adding a multiple parameter.

class FirstKata
  def sum(upper_limit, multiple)
    sum = 0

    upper_limit.to_i.times do |i|
      sum += i if (i % multiple == 0)
    end

    sum
  end
end

class FirstKataTest < Test::Unit::TestCase
  def test_sum
    assert_equal(18, FirstKata.new.sum(10, 3))
  end
end

This parameter is a number. So, we indeed have a more generic solution, but it only works for 1 multiple at a time.
Lets fix this.

class FirstKata
  def sum(upper_limit, multiples)
    sum = 0

    upper_limit.to_i.times do |i|
      sum += i if is_multiple?(i, multiples)
    end

    sum
  end

  def is_multiple?(number, multiples)
    multiple = false

    multiples.each do |j|
      if (number % j == 0)
        multiple = true
      end
    end

    multiple
  end
end

class FirstKataTest < Test::Unit::TestCase
  def test_sum
    assert_equal(23, FirstKata.new.sum(10, [3,5]))
    assert_equal(233168, FirstKata.new.sum(1000, [3,5]))
  end
end

Now we can receive a list of multiples and thus our solution is a generic one.
But can we still improve our code?

I think so...

class FirstKata
  def sum(upper_limit, multiples)
    sum = 0

    upper_limit.to_i.times do |i|
      sum += i if is_multiple?(i, multiples)
    end

    sum
  end

  def is_multiple?(number, multiples)
    multiples.each do |j|
      return true if (number % j == 0)
    end

    false
  end
end

class FirstKataTest < Test::Unit::TestCase
  def test_is_multiple?
    assert_equal(true, FirstKata.new.is_multiple?(2, [2]))
    assert_equal(true, FirstKata.new.is_multiple?(6, [3]))
    assert_equal(true, FirstKata.new.is_multiple?(6, [3, 2]))
    assert_equal(true, FirstKata.new.is_multiple?(15, [3, 5]))
  end

  def test_sum
    assert_equal(23, FirstKata.new.sum(10, [3, 5]))
    assert_equal(233168, FirstKata.new.sum(1000, [3, 5]))
  end
end

And we now have a more concise version of the generic solution.

No comments:

Post a Comment