## Pages

### Yahtzee in ruby in cyber-dojo

I've been doing the Yahtzee kata in cyber-dojo to improve my Ruby. During the 247 increments I learned about...
• any?
• send
• [lo...hi]
• reduce
• :+
It's also on pastie if you like a black background. You can use Cyber-Dojo to step through the diffs of every single increment!
```module Yahtzee

def self.score dice, category, n=nil
return -1 if invalid(dice, category)
if category == :value
value(dice, n)
else
send(category, dice)
end
end

def self.chance dice
dice.reduce(:+)
end

def self.yahtzee dice
dice.uniq.length == 1 ? 50 : 0
end

def self.value dice, n
dice.count{|die| die == n } * n
end

def self.one_pair dice
die(tally(dice).find{|n| pair?n }) * 2
end

def self.two_pair dice
score_tally dice, [2,2]
end

def self.three_of_a_kind dice
score_tally dice, [3]
end

def self.four_of_a_kind dice
score_tally dice, [4]
end

def self.full_house dice
score_tally dice, [3,2]
end

def self.small_straight dice
dice.sort == [1,2,3,4,5] ? 15 : 0
end

def self.large_straight dice
dice.sort == [2,3,4,5,6] ? 20 : 0
end

#- - - - - - - - - - - - - - - - - - - - - - -

def self.categories
[:value, :chance, :yahtzee, :one_pair, :two_pair,
:three_of_a_kind, :four_of_a_kind, :full_house,
:small_straight, :large_straight
]
end

def self.invalid dice, category
dice == nil \
or dice.length != 5 \
or dice.any?{|die| die < 1 or die > 6 } \
or !categories.include? category
end

def self.score_tally dice, pattern
starts?(pattern, tallies(dice)) \
? sum(dice, pattern.length) \
: 0
end

def self.starts? short, long
long[0...short.length] == short
end

def self.tallies dice
tally(dice).map{|n| count(n) }
end

def self.rolls dice
tally(dice).map{|n| die(n) }
end

def self.tally dice
dice.uniq.map {|die| [dice.count(die),die] }.sort.reverse
end

def self.sum dice, n
sum2(rolls(dice)[0...n], dice)
end

def self.sum2 scorers, dice
dice.select {|die| scorers.include?die }.reduce(:+)
end

def self.pair? n
count(n) == 2
end

def self.count n
n[0]
end

def self.die n
n ? n[1] : 0
end

end
```
I challenged myself to write the code in a functional style with no local variables - it's a bit 'dense' in places as a result.