Skip to content

Instantly share code, notes, and snippets.

@dariodaich
Last active February 22, 2016 00:31
Show Gist options
  • Save dariodaich/1d1cb5d90215f0283dd5 to your computer and use it in GitHub Desktop.
Save dariodaich/1d1cb5d90215f0283dd5 to your computer and use it in GitHub Desktop.
Solution to Ruby "greed koan".
# Greed is a dice game where you roll up to five dice to accumulate
# points. The following "score" function will be used to 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
class DiceRoll
def initialize(dice_rolls)
@roll_count = count_rolls(dice_rolls)
@score = 0
end
def calculate_score
return 0 if @roll_count.empty?
score_three_of_a_kind { |number| number == 1 ? 1000 : number * 100 }
score_single_rolls
@score
end
private
def score_three_of_a_kind(&block)
@roll_count.dup.each do |number, count|
if count >= 3
@score += block.call(number)
@roll_count[number] -= 3
end
end
end
def score_single_rolls
@roll_count.each do |number, count|
@score += count * 100 if number == 1
@score += count * 50 if number == 5
end
end
def count_rolls(dice_rolls)
roll_count = Hash.new { |rolls, number| rolls[number] = 0 }
dice_rolls.each { |n| roll_count[n] += 1 }
roll_count
end
end
puts "When empty"
p DiceRoll.new([]).calculate_score # => 0
puts "With:"
puts "1 roll"
p DiceRoll.new([5]).calculate_score # => 50
p DiceRoll.new([1]).calculate_score # => 100
p DiceRoll.new([2]).calculate_score # => 0
puts "2 rolls"
p DiceRoll.new([1,1]).calculate_score # => 200
p DiceRoll.new([1,5]).calculate_score # => 150
p DiceRoll.new([5,5]).calculate_score # => 100
p DiceRoll.new([2,5]).calculate_score # => 50
p DiceRoll.new([1,2]).calculate_score # => 100
puts "3 rolls"
p DiceRoll.new([1,1,1]).calculate_score # => 1000
p DiceRoll.new([5,5,5]).calculate_score # => 500
p DiceRoll.new([2,2,2]).calculate_score # => 200
p DiceRoll.new([5,1,5]).calculate_score # => 200
p DiceRoll.new([1,1,2]).calculate_score # => 200
puts "4 rolls"
p DiceRoll.new([1,1,1,1]).calculate_score # => 1100
p DiceRoll.new([1,1,1,5]).calculate_score # => 1050
p DiceRoll.new([5,1,5,5]).calculate_score # => 600
p DiceRoll.new([5,5,5,5]).calculate_score # => 550
p DiceRoll.new([5,1,5,5]).calculate_score # => 600
p DiceRoll.new([1,2,3,4]).calculate_score # => 100
puts "5 rolls"
p DiceRoll.new([1,1,1,5,5]).calculate_score # => 1100
p DiceRoll.new([5,5,5,1,1]).calculate_score # => 700
p DiceRoll.new([3,3,3,1,5]).calculate_score # => 450
p DiceRoll.new([4,4,4,1,1]).calculate_score # => 600
p DiceRoll.new([2,5,2,2,5]).calculate_score # => 300
p DiceRoll.new([2,3,1,1,1]).calculate_score # => 1000
p DiceRoll.new([1,1,3,2,1]).calculate_score # => 1000
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment