Skip to content

Instantly share code, notes, and snippets.

@enriquez
Created December 14, 2010 14:17
Show Gist options
  • Save enriquez/740479 to your computer and use it in GitHub Desktop.
Save enriquez/740479 to your computer and use it in GitHub Desktop.
require 'test/unit'
class Frame
attr_reader :rolls
def initialize(first_roll)
@rolls = [first_roll]
end
def << pins
@rolls << pins
end
def score
@rolls.inject(0) { |total,roll| total + roll }
end
def score_with_bonus(remaining_frames)
s = score
unless remaining_frames.empty?
next_rolls = remaining_frames[0..1].map{|f| f.rolls }.flatten
s += next_rolls[0].to_i if self.closed?
s += next_rolls[1].to_i if self.strike?
end
s
end
def unclosed?
@rolls.size == 1 && !strike?
end
def closed?
score == 10
end
def strike?
@rolls.first == 10
end
end
class Game
def initialize
@frames = []
end
def roll pins
if @frames.size == 10 || (!@frames.empty? && @frames.last.unclosed?)
@frames.last << pins
else
@frames << Frame.new(pins)
end
end
def score
s = 0
@frames.each_with_index do |frame,i|
s += frame.score_with_bonus(@frames[(i+1)..-1])
end
s
end
end
class GameTest < Test::Unit::TestCase
def setup
@g = Game.new
end
def test_gutter_game
rolls 20.gutters
# roll_many(20,0)
assert_equal 0, @g.score
end
def test_all_ones
rolls '1'*20
assert_equal 20, @g.score
end
def test_one_spare
rolls '553' + 17.gutters
assert_equal 16, @g.score
end
def test_one_strike
rolls 'x34' + 16.gutters
assert_equal 24, @g.score
end
def test_almost_perfect
rolls 'x'*10+'00'
assert_equal 270, @g.score
end
def test_perfect
rolls 'x'*12
assert_equal 300, @g.score
end
def test_crazy_normal_game
rolls 'x |5/|3-|4/|x |24|81|x |x |1/3'
assert_equal 141, @g.score
end
def test_rolls
assert_equal 'x5532', numerify_rolls('x|5/|32')
end
def rolls string
numerify_rolls(string).each_char do |c|
@g.roll c.to_i
end
end
def numerify_rolls string
string.gsub(/[|\s]/,'').gsub(/(\d)\//){"#{$1}#{10-$1.to_i}"}
end
end
class String
alias :normal_to_i :to_i
def to_i
self == 'x' ? 10 : normal_to_i
end
end
class Fixnum
def gutters
'0' * self
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment