V
V
vladimir_e2012-04-25 19:14:20
Ruby on Rails
vladimir_e, 2012-04-25 19:14:20

Is a Ruby Koans solution good enough?

Hello everyone on the Ruby path.
To consolidate my programming skills in Ruby, I decided to finish off Ruby Koans .
To explain what it is, I'll quote egoholic from his post :

… the Ruby Koans project, which is a learning environment built around Test::Unit. The bottom line is that all tests pass correctly as a result of your editing the content of the test matchers. RubyKoans can be downloaded to your machine, but especially for lazy people like me, a web interface has been implemented, which means that you don’t need to install anything, just go to the address below and fill in the fields so that there are no errors in the matchers. Project website: rubykoans.com/ , online version: koans.heroku.com/.

My question is about this part: about_scoring_project
Task: Write a method that calculates the score from a roll of dice.
The argument is an array containing up to 5 values. For example [1, 4] or [4, 4, 4, 1, 5]
Counting rules:
  • Three units give 1000 points.
  • Any other number occurring 3 times is 100 times that number (three fives is 500).
  • The occurring unit gives 100. Except when it is included in a set of three units (see point 1).
  • Five gives 50 Except when it is included in a set of three fives (see point 2).
  • Everything else is 0.

How do you like my decision? The image of the person who came from PHP is not looked through?
<pre><code class="ruby">def score(dice)
  # no dice given
  return 0 if dice.empty?

  total = 0

  # find triple match
  # collect duplicates into array (not more than 3)
  duplicates = dice.map do |n|
    n if dice.count{|d| d == n} &gt; 2
  end.compact
  # get number or nil
  triple = duplicates.pop

  # if there IS triple match
  if triple
    # triple one gives 1000
    if triple == 1
      total += 1000
    # other values give x100
    else
      total += triple*100
    end
    # remove those numbers from the collection
      # also ensure that only 3 array items can be removed
    array_min_size = dice.count - 3
    dice = dice.delete_if do |n|
      true if (n == triple && dice.count &gt; array_min_size)
    end 
  end

  # look for 1 or 5
  dice.each do |n|
    total += 50 if n == 5
    total += 100 if n == 1
  end

  return total
end

I would be very grateful for any criticism.
If you've also played with Ruby Koans, post your solutions here. I am sure that everyone who has passed this part goes to look for how others have done it.

Answer the question

In order to leave comments, you need to log in

4 answer(s)
J
jj_killer, 2012-04-26
@vladimir_e

Something like this, I didn’t quite understand whether [1, 1, 1, 1, 1, 1] could get caught.

def score(dice)
  result = 0;

  (1..6).each do |digit|
    multiplier = 100
    multiplier = 1000 if digit == 1
    triple  = dice.count(digit) / 3 # принять во внимание [1, 1, 1, 1, 1, 1]
    result += digit * multiplier * triple
  end

  result += dice.count(1) % 3 * 100
  result += dice.count(5) % 3 * 50
end

T
traneblow, 2012-04-25
@traneblow

Still, it is very difficult to switch from PHP to Ruby. I can't get used to it myself.

J
jj_killer, 2012-04-25
@jj_killer

It still looks like. But this will pass with time. I will duplicate here some of the recommendations traditional for Ruby.

  1. Don't use return if you can do without it.
  2. Avoid nested ifs. Relevant not only for the quality of the code, but also for performance.
  3. In general, avoid unnecessary logic, like:
    return 0 if dice.empty?
  4. Well, the algorithm itself is a bit short, I would have done it differently.

Now I'll try to rewrite it in my own way.

A
aaz86, 2012-04-25
@aaz86

The tests pass, although to be honest these tests are not enough to guarantee the correctness of the implementation

def score(dice)
  # You need to write this method

  digits = Hash.new(0)
  dice.each { |n| digits[n] += 1  }

  result = 0

  result += 1000 if digits[1] >= 3           # 1

  (digits.keys - [1]).each do |n|            # 2
    result += n * 100 if digits[n] >= 3
  end

  result += 100 * (digits[1] % 3)            # 3

  result += 50 * (digits[5] % 3)             # 4

  result
end

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question