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
- :+
- module names start with a capital
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.