Joshua Cody - 9 months ago 31

Ruby Question

I'm working my way through the Ruby Koans in order to try and learn Ruby, and so far, so good. I've gotten to the greed koan, which at the time of this writing is 183. I've got a working solution, but I feel like I've cobbled together just a bunch of if/then logic and that I'm not embracing Ruby patterns.

In the following code, are there ways you would point me to more fully embracing Ruby patterns? (My code is wrapped in "MY CODE [BEGINS|ENDS] HERE" comments.

`# Greed is a dice game where you roll up to five dice to accumulate`

# points. The following "score" function will be used calculate the

# score of a single roll of the dice.

#

# A greed roll is scored as follows:

#

# * A set of three ones is 1000 points

#

# * A set of three numbers (other than ones) is worth 100 times the

# number. (e.g. three fives is 500 points).

#

# * A one (that is not part of a set of three) is worth 100 points.

#

# * A five (that is not part of a set of three) is worth 50 points.

#

# * Everything else is worth 0 points.

#

#

# Examples:

#

# score([1,1,1,5,1]) => 1150 points

# score([2,3,4,6,2]) => 0 points

# score([3,4,5,3,3]) => 350 points

# score([1,5,1,2,4]) => 250 points

#

# More scoring examples are given in the tests below:

#

# Your goal is to write the score method.

# MY CODE BEGINS HERE

def score(dice)

# set up basic vars to handle total points and count of each number

total = 0

count = [0, 0, 0, 0, 0, 0]

# for each die, make sure we've counted how many occurrencess there are

dice.each do |die|

count[ die - 1 ] += 1

end

# iterate over each, and handle points for singles and triples

count.each_with_index do |count, index|

if count == 3

total = doTriples( index + 1, total )

elsif count < 3

total = doSingles( index + 1, count, total )

elsif count > 3

total = doTriples( index + 1, total )

total = doSingles( index + 1, count % 3, total )

end

end

# return the new point total

total

end

def doTriples( number, total )

if number == 1

total += 1000

else

total += ( number ) * 100

end

total

end

def doSingles( number, count, total )

if number == 1

total += ( 100 * count )

elsif number == 5

total += ( 50 * count )

end

total

end

# MY CODE ENDS HERE

class AboutScoringProject < EdgeCase::Koan

def test_score_of_an_empty_list_is_zero

assert_equal 0, score([])

end

def test_score_of_a_single_roll_of_5_is_50

assert_equal 50, score([5])

end

def test_score_of_a_single_roll_of_1_is_100

assert_equal 100, score([1])

end

def test_score_of_multiple_1s_and_5s_is_the_sum_of_individual_scores

assert_equal 300, score([1,5,5,1])

end

def test_score_of_single_2s_3s_4s_and_6s_are_zero

assert_equal 0, score([2,3,4,6])

end

def test_score_of_a_triple_1_is_1000

assert_equal 1000, score([1,1,1])

end

def test_score_of_other_triples_is_100x

assert_equal 200, score([2,2,2])

assert_equal 300, score([3,3,3])

assert_equal 400, score([4,4,4])

assert_equal 500, score([5,5,5])

assert_equal 600, score([6,6,6])

end

def test_score_of_mixed_is_sum

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

assert_equal 550, score([5,5,5,5])

end

end

Thanks so much to any help you can give as I try to get my head around Ruby.

Answer

Looks OK. I might have written some things slightly differently, say:

```
def do_triples number, total
total + (number == 1 ? 1000 : number * 100)
end
```

If you want to do something that few languages other than Ruby can do, I suppose the following *might* be justifiable under DIE and DRY, on alternate Tuesdays, but I don't think those Ruby maxims were really intended to apply to common subexpression elimination. Anyway:

```
def do_triples number, total
total +
if number == 1
1000
else
number * 100
end
end
def do_triples number, total
if number == 1
1000
else
number * 100
end + total
end
```