开发者

Why does Ruby include? evaluate to nil?

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 1开发者_Go百科150).

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?


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).


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜