- require 'benchmark'
- class Gary
- # https://gist.github.com/1089115
- def score(dice)
- score_counts(dice).inject(0) {|score, pair| score + frequency_score(pair)}
- end
- def frequency_score(pair)
- triple_score(pair) + single_score(pair)
- end
- def triple_score(pair)
- (pair[:count] / 3) * triple_multiplier(pair[:score])
- end
- def triple_multiplier(score)
- score == 1 ? 1000 : score * 100
- end
- def single_score(pair)
- (pair[:count] % 3) * single_multiplier(pair[:score])
- end
- def single_multiplier(score)
- case score
- when 1; 100
- when 5; 50
- else ; 0
- end
- end
- def score_counts(dice)
- (1..6).map do |score|
- {:score => score, :count => dice.select{|d| d == score}.size}
- end
- end
- end
- class Jak
- # https://gist.github.com/1088610
- def score(dice)
- score = 0
- return score if dice.empty?
- counts = [0,0,0,0,0,0]
- dice.each {|d| counts[d-1] += 1 }
- ones, twos, threes, fours, fives, sixes = counts
- if ones >= 3 then
- score += 1000 + ((ones-3) * 100)
- else
- score += (ones * 100)
- end
- if fives >= 3 then
- score += 500 + ((fives-3) * 50)
- else
- score += fives * 50
- end
- score += 200 if twos >= 3
- score += 300 if threes >= 3
- score += 400 if fours >= 3
- score += 600 if sixes >= 3
- score
- end
- end
- class Serbrech
- # https://gist.github.com/906429
- def triple?(dice, val)
- dice.count {|die| die == val} >= 3
- end
- def handle_triples(dice)
- return 0 if dice.empty?
- return 350 if triple? dice, 5
- return 700 if triple? dice, 1
- return_value = 0
- (2..6).each do |item|
- return_value = item * 100 if triple? dice, item
- end
- return return_value
- end
- def score(dice)
- total = handle_triples dice
- dice.each do |die|
- total += 50 if die == 5
- total += 100 if die == 1
- end
- total
- end
- end
- class Kevin
- # https://gist.github.com/1088913
- def score(dice)
- # Hash holds values seen in the roll and the number of duplicates for each
- h = Hash.new(0)
- dice.each { | d | h.store(d, h[d]+1) }
- score = 0
- score += h[1] * 100
- score += 700 if h[1] >= 3 # 1000 bonus points, minus the 3 * 100 points for the 1's in the set
- score += 200 if h[2] >= 3
- score += 300 if h[3] >= 3
- score += 400 if h[4] >= 3
- score += h[5] * 50
- score += 350 if h[5] >= 3 # 500 bonus points, minus the 3 * 50 points for the 5's in the set
- score += 600 if h[6] >= 3
- score
- end
- end
- class Glebm
- # answer by Glebm at http://codereview.stackexchange.com/questions/423/is-this-good-ruby-ruby-koans-greed-task
- def score(dice)
- score = 0
- # Below is equivalent to:
- # counts = dice.inject(Hash.new(0)) { |h, x| h[x] += 1; h }
- counts = Hash.new(0)
- dice.each do |x|
- counts[x] += 1
- end
- (1..6).each do |i|
- if counts[i] >= 3
- if i == 1
- score += 1000
- else
- score += 100 * i
- end
- counts[i] = [counts[i] - 3, 0].max
- end
- if i == 1
- score += 100 * counts[i]
- elsif i == 5
- score += 50 * counts[i]
- end
- end
- score
- end
- end
- class Felix
- # from Felix Alcala http://codereview.stackexchange.com/questions/423/is-this-good-ruby-ruby-koans-greed-task
- def score(dice)
- patterns = {[1,1,1]=>1000, [2,2,2]=>200, [3,3,3]=>300, [4,4,4]=>400,
- [5,5,5]=>500, [6,6,6]=>600, 1=>100, 5=>50}
- sorted = dice.sort
- triple = patterns[sorted[0..2]]
- single = patterns[sorted[0]]
- if triple
- partial_score = triple
- rest = sorted[3..-1]
- elsif single
- partial_score = single
- rest = sorted[1..-1]
- else
- partial_score = 0
- rest = sorted[1..-1]
- end
- if rest
- partial_score + score(rest)
- else
- partial_score
- end
- end
- end
- n = 500000
- jak = Jak.new
- serbrech = Serbrech.new
- gary = Gary.new
- kevin = Kevin.new
- glebm = Glebm.new
- felix = Felix.new
- [[], [5], [1], [1,5,5,1], [2,3,4,6], [1,1,1]].each do |to_score|
- Benchmark.bm do |x|
- puts "Results for: " + to_score.inspect
- x.report("jak: ") { for i in 1..n; jak.score(to_score); end }
- x.report("serbrech:") { for i in 1..n; serbrech.score(to_score); end }
- x.report("gary: ") { for i in 1..n; gary.score(to_score); end }
- x.report("kevin: ") { for i in 1..n; kevin.score(to_score); end }
- x.report("glebm: ") { for i in 1..n; glebm.score(to_score); end }
- x.report("felix: ") { for i in 1..n; felix.score(to_score); end }
- puts "-----------------------------------------------------"
- end
- end