tags:

views:

59

answers:

2

So, I'm a total nuby working through http://www.rubykoans.com/ and I'm stuck on about_scoring_project.rb. This is my stab at the score method.

def score(dice)
  score = 0;
  if dice.respond_to?("include?") then
    # add 1000 points if rolled 3 ones
    score += 1000 if dice.include?([1, 1, 1])

    # add 100 points times die face value if rolled 3 of a number between 2 and 6
    (2...6).each do |die|
        score += die*100 if dice.include?([die, die, die])

      # award points for each 1 or 5 not a part of a set of 3
      leftovers = dice - [1,1,1]
      leftovers -= [5,5,5]
      leftovers.each do |leftover|
        score += 100 if leftover == 1
        score += 50 if leftover == 5
      end
    end
  end
  score
end

class AboutScoringAssignment < EdgeCase::Koan
  def test_score_examples
    assert_equal 1150, score([1,1,1,5,1])
    assert_equal 0, score([2,3,4,6,2])
    assert_equal 350, score([3,4,5,3,3])
    assert_equal 250, score([1,5,1,2,4])
  end
end

In the call to score from the first assert_equal, I would expect dice.include?([1,1,1]) to evaluate to true, but it's evaluating to nil (and score is returning 0 instead of 1150).

I tried this separately...

require 'test/unit'

class EnumerableTests < Test::Unit::TestCase
  def test_include
    my_enumerable = [1,1,1,5,1]
    assert true, my_enumerable.include?([1,1,1])    
  end
end

...and the test passes, so I don't know why I'm getting nil in my score method.

Anybody see what I'm doing wrong?

+1  A: 

Minor nitpick: Array#include? always returns true or false, never nil.

To answer your question: x.include?(y) tests whether y is an element of x, not whether it's a subarray.

[1,1,1,5,1].include?([1,1,1]) returns false because [1,1,1] is not an element of the array [1,1,1,5,1]. [[1,1,1],[5,1]].include?([1,1,1])) would return true.

There is no method in ruby that checks whether an array is a subarray of a another array, but you can easily write it as arr1.each_cons(arr2.size).include?(arr2) (needs require 'enumerator' in 1.8.6). This is O(arr1.size*arr2.size) though.

If you want it in O(arr1.size + arr2.size), you can implement the Knuth-Morris-Pratt algorithm (which is meant to find substrings, but works equally well for finding subarrays as they are essentially the same thing).

sepp2k
Thanks...I'm getting the idea that it's returning nil from the RubyMine debugger. Maybe I don't understand the debugger, or maybe it's a RubyMine bug.
Marvin
Thanks for the arr1.each_cons(arr2.size).include?(arr2) suggestion - works great for me!
Marvin
A: 

I think you misunderstand what Array#include? does. It searches for its argument as an element of the array, not as a subsequence. Your test_include will always pass, because you give the assert function true as its first argument. You should either use assert_equal with these arguments or (preferably) just get rid of the first argument.

wdebeaum
Thanks for clarifying for me.
Marvin