ruby koans

EdgeCase’s Ruby Koans are a great way to get started with the Ruby programming language. I’ve worked through them once before and have had some free time at work so decided to work through them again.

The quality of the koans are normally excellent, there are a few times where a comment is left in the code to make you think, and you really wish that there was an answer key somewhere. There are also what look like a few errors in the code

In about_sandwich_code.rb, the find_line and find_line2 functions don’t seem to make much sense. You would imagine a function would find a line matching a given regular expression, but the regular expression is hardcoded to /e/ which doesn’t seem very realistic. This is the original.

def find_line(file_name)
  file = open(file_name)
  while line = file.gets
    return line if line.match(/e/)
  end
ensure
  file.close if file
end

A more realistic function would be

def find_line(file_name, regex)
  file = open(file_name)
  while line = file.gets
    return line if line.match(regex)
  end
ensure
  file.close if file
end

I’m sure this was done to simplify the exercise, but it violates the rule of least surprise by adding magic functionality to the function.

In the last function of about_scoring_project.rb, named test_score_of_mixed_is_sum, the first assert reads

 assert_equal 50, score([2, 5, 2, 2, 3]) 

The rules of the game clearly specify that

# * A set of three numbers (other than ones) is worth 100 times thenumber. (e.g. three fives is 500 points).
# ...
# * A five (that is not part of a set of three) is worth 50 points.

This means that the score should be 200 (for the set of three 2′s) + 50 (for the 5) = 250. The first assert should be changed to

 assert_equal 250, score([2, 5, 2, 2, 3]) 

If you are interested in learning ruby, this is an indispensable way to learn not just the syntax, but to get the flavor, and to start thinking in ruby.

Expand this block of source to see my solution

def score(dice)
  result = 0
  counter = {}
  (1..6).each { |x| counter[x] = 0 }
  dice.each { |d| counter[d] += 1 }
  if counter[1] >= 3
    result += 1000
    counter[1] -= 3
  end 

  (2..6).each do |x|
    if counter[x] >= 3
      result += (100 * x)
      counter[x] -= 3
    end
  end

  result += (counter[1] * 100)
  result += (counter[5] * 50)
end

Tags: ,

5 comments

  1. My impression is that is a set of three numbers in a row.
    In the case of this Koan the three 2 are not in a row and that is why they have no value.

  2. Nice solution! My only suggestion is this:

    counter = Hash.new(0)

    … so that you don’t need the next line of setting them all to 0.

Leave a comment