## Pages

### Bowling Game in Ruby

John Cleary (@TheRealBifter) is doing a nice project - The 12 TDD's of Xmas. Day 9 was the Bowling Game problem. I did it in Ruby. Here's the code from traffic-light 100.

Tests first:
```require './score'
require 'test/unit'

class TestScore < Test::Unit::TestCase

def test_score_uninteresting_game
#           7     7     7     7    7 = 35
#        6     6     6     6     6   = 30
balls = "51|52|51|52|51|52|51|52|51|52"
assert_equal 65, score(balls)
end

def test_score_all_frames_5_spare
#           15    15    15    15    15 = 75
#        15    15    15    15    15    = 75
balls = "5/|5/|5/|5/|5/|5/|5/|5/|5/|5/|5"
assert_equal 150, score(balls)
end

def test_perfect_score
#          30  30  30  30  30 = 150
#        30  30  30  30  30   = 150
balls = "X|X|X|X|X|X|X|X|X|X|XX"
assert_equal 300, score(balls)
end

def test_10_strikes_then_33
#          30  30  30  30  16 = 136
#        30  30  30  30  23   = 143
balls = "X|X|X|X|X|X|X|X|X|X|33"
assert_equal 279, score(balls)
end

def test_game_with_spare_in_middle_of_strikes
#          20   30  30  30  30    = 140
#        25  20   30  30  30      = 135
balls = "X|X|5/|X|X|X|X|X|X|X|XX"
assert_equal 275, score(balls)
end

def test_game_with_strike_in_middle_of_spares
#           15    20   15    13    20  = 83
#        13    11    20   14    12     = 70
balls = "2/|3/|5/|1/|X|3/|5/|4/|3/|2/|X"
assert_equal 153, score(balls)
end

def test_game_with_zero_balls
#           8     7     7     7     7 = 36
#        6     5     6     6     6    = 29
balls = "51|62|50|52|51|52|51|52|51|52"
assert_equal 65, score(balls)
end

def test_game_with_dash_as_zero_balls
#           8     7     7     7     8 = 37
#        6     5     6     6     6    = 29
balls = "51|62|5-|52|51|52|51|52|51|62"
assert_equal 66, score(balls)
end

end
```
Code second:
```def score(balls)
frames = (balls).split("|")
while frames.length != 12
frames << "0"
end
frames.each_cons(3).collect{ |frame|
frame_score(frame)
}.inject(:+)
end

def frame_score(frames)
if strike? frames[0]
10 + strike_bonus(frames[1..2])
elsif spare? frames[0]
10 + ball_score(frames[1][0])
else
frames[0].chars.collect{ |ball|
ball_score(ball)
}.inject(:+)
end
end

def strike_bonus(frames)
if frames[0] == "XX"
20
elsif strike? frames[0]
10 + ball_score(frames[1][0])
elsif spare? frames[0]
10
else
ball_score(frames[0][0]) + ball_score(frames[0][1])
end
end

def ball_score(ball)
if strike? ball
10
else
ball.to_i
end
end

def strike?(frame)
frame == "X"
end

def spare?(frame)
frame[-1] == "/"
end
```
It took me a while to realize that each_slice should have been each_cons. You can replay my entire progression (warts and all) on Cyber-Dojo (naturally).