bennett_an
bennett_an

Reputation: 1708

Ruby Koans Scoring Project. undefined method `length' for nil:NilClass

I am BRAND new to Ruby, and programing in general. I'm working my way through the Ruby Koans. I've made it up to 176/274 before getting stuck.
It's the "Scoring Project" I need to write a method to calculate the score of a given dice roll.
This may not be the most elegant code you've ever seen but here's what I came up with:

def score(dice)
  tally = 0
  tally += (dice.sort.to_s[/[1]+/].length % 3) * 100
  if dice.sort.to_s[/[1]+/].length >= 3
    tally += 1000
  end
  tally = tally + (dice.sort.to_s[/[5]+/].length % 3) * 50
  if dice.sort.to_s[/[5]+/].length >= 3
    tally += 500
  end
  if dice.sort.to_s[/[2]+/].length >= 3
    tally += 200
  end
  if dice.sort.to_s[/[3]+/].length >= 3
    tally += 300
  end
  if dice.sort.to_s[/[4]+/].length >= 3
    tally += 400
  end
  if dice.sort.to_s[/[6]+/].length >= 3
    tally += 600
  end
  return tally
end

The first test is: score([]) needs to return 0

When I run it I get "undefined method `length' for nil:NilClass" (the line referenced is the first instance of .length) This tells me that "dice.sort.to_s[/[1]+/]" with "score([])" is nil, but when i run it in irb>> it is 0.

What gives?

Upvotes: 0

Views: 1396

Answers (2)

Deleteman
Deleteman

Reputation: 8700

What Ruby version are you using? I'm using 1.9.2 and my IRB gives me the same error since the regexp returns nil if there is no match. Being dice = [] a border case, you could add a check for that on the first lines of your code in order to return 0 then.

I did the RubyKoans today and even though, my code is not prettier than yours, maybe it'll help you out a bit:

def score(dice)

points = 0
dice.sort!
  nmbrs = Array.new
       dice.each { |n|
               nmbrs[n] = dice.select { |nm| nm == n}
       } 

 n = 0
 nmbrs.each { |vals|
      n = n + 1
      if(vals.nil?)
              next
      end
      if(vals.count >= 3)

              points += (n-1)*100 if (n-1) != 1
              points += 1000 if (n-1) == 1

              if vals.size > 3
                      if (n-1) == 1
                              points += 100 * (vals.size - 3)
                      else
                              if (n-1) == 5
                                      points += 50 * (vals.size - 3)
                            end
                      end

              end
      else
            points += 100 * (vals.count) if (n-1) == 1
            points += 50 * (vals.count) if (n-1) == 5
      end
   }

    points

 end

Sorry about the crappy function, but it does work, so it might give you an idea of how to solve that particular problem.

Good luck!

Upvotes: 0

bennett_an
bennett_an

Reputation: 1708

OK. Got it.

Huge apologies, I had said that running "dice.sort.to_s[/[1]+/]" was returning zero not nil, it must have been because it had some storred value i didn't know about. When i ran "[].sort.to_s[/[1]+/]" it returned nil properly. So I nested each of my if statements in a check to make sure there wasn't a nil value.

def score(dice)
  tally = 0
  if dice.sort.to_s[/[1]+/]
    tally += (dice.sort.to_s[/[1]+/].length % 3) * 100
    if dice.sort.to_s[/[1]+/].length >= 3
      tally += 1000
    end
  end
  if dice.sort.to_s[/[5]+/]
    tally += (dice.sort.to_s[/[5]+/].length % 3) * 50
    if dice.sort.to_s[/[5]+/].length >= 3
      tally += 500
    end
  end
  if dice.sort.to_s[/[2]+/]
    if dice.sort.to_s[/[2]+/].length >= 3
      tally += 200
    end
  end
  if dice.sort.to_s[/[3]+/]
    if dice.sort.to_s[/[3]+/].length >= 3
      tally += 300
    end
  end
  if dice.sort.to_s[/[4]+/]
    if dice.sort.to_s[/[4]+/].length >= 3
      tally += 400
    end
  end
  if dice.sort.to_s[/[6]+/]
    if dice.sort.to_s[/[6]+/].length >= 3
      tally += 600
    end
  end
  return tally
end

All test's pass.

Upvotes: 0

Related Questions