Created
June 28, 2018 17:33
-
-
Save bjjb/80fccd24ba87c3352bf8ec30fa4e6e90 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'minitest/autorun' | |
# A Ruby solution to Uncle Bob's Bowling Game | |
# https://programmingpraxis.com/2009/08/11/uncle-bobs-bowling-game-kata/ | |
module Bowling | |
module_function | |
def strike?(scores) | |
scores&.first == 10 | |
end | |
def spare?(scores) | |
scores&.length >= 2 && scores[0..1].sum == 10 | |
end | |
def bonus?(scores) | |
strike?(scores) || spare?(scores) | |
end | |
def score_frame(scores) | |
score = scores[0..1].compact.sum | |
if (spare?(scores) || strike?(scores)) && scores[2] | |
score += scores[2] | |
end | |
score | |
end | |
def score_game(scores) | |
return 0 if scores.nil? || scores.empty? | |
score = score_frame(scores) | |
if strike?(scores) | |
score += score_game(scores[1..-1]) | |
else | |
score += score_game(scores[2..-1]) | |
end | |
score | |
end | |
end | |
describe Bowling do | |
include Bowling | |
describe '#strike?' do | |
it 'detects a strike in the first position' do | |
assert strike?([10]) | |
end | |
it 'recognizes other types of rolls' do | |
refute strike?([]) | |
refute strike?([0]) | |
refute strike?([0, 10]) | |
end | |
end | |
describe '#spare?' do | |
it 'recognizes spares from the sum of the first two rolls' do | |
assert spare?([5, 5]) | |
assert spare?([1, 9]) | |
end | |
it 'recognizes non-spares' do | |
refute spare?([]) | |
refute spare?([9]) | |
refute spare?([5, 4]) | |
refute spare?([1, 10]) | |
end | |
end | |
describe '#score_frame' do | |
it 'sums the first two results' do | |
assert_equal 0, score_frame([0, 0]) | |
assert_equal 2, score_frame([1, 1]) | |
end | |
it 'handles the end of the game' do | |
assert_equal 0, score_frame([]) | |
assert_equal 1, score_frame([1]) | |
assert_equal 9, score_frame([9]) | |
end | |
describe 'for a spare' do | |
it 'adds on the next roll for a spare' do | |
assert_equal 11, score_frame([1, 9, 1]) | |
end | |
it "doesn't add on the fourth roll" do | |
assert_equal 11, score_frame([1, 9, 1, 2]) | |
end | |
end | |
describe 'for a strike' do | |
it 'adds on the next roll' do | |
assert_equal 11, score_frame([10, 1]) | |
end | |
it "adds on the third roll" do | |
assert_equal 12, score_frame([10, 1, 1]) | |
end | |
it "adds on the fourth roll" do | |
assert_equal 12, score_frame([10, 1, 1, 1]) | |
end | |
end | |
end | |
describe '#score_game' do | |
describe 'a gutter game' do | |
it 'adds all the scores and gets zero' do | |
assert_equal 0, score_game([0]) | |
assert_equal 0, score_game([0, 0, 0]) | |
assert_equal 0, score_game([]) | |
end | |
end | |
describe 'a normal game' do | |
it 'adds all the scores' do | |
assert_equal 6, score_game([1, 2, 3]) | |
end | |
end | |
describe 'a game with spares' do | |
it 'adds all the scores with bonuses' do | |
assert_equal 16, score_game([8, 2, 3]) | |
assert_equal 17, score_game([8, 2, 3, 1]) | |
assert_equal 29, score_game([8, 2, 3, 1, 9, 1, 1]) | |
end | |
end | |
describe 'a game with strikes' do | |
it 'adds the bonuses for the strikes' do | |
assert_equal 10, score_game([10]) | |
assert_equal 30, score_game([10, 10]) | |
assert_equal 33, score_game([10, 10, 1]) | |
assert_equal 300, score_game([10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10]) | |
end | |
end | |
describe 'a game with strikes and spares' do | |
it 'adds the scores properly' do | |
assert_equal 32, score_game([1, 2, 3, 4, 5, 5, 6]) | |
assert_equal 35, score_game([1, 2, 3, 4, 5, 5, 6, 3]) | |
assert_equal 45, score_game([1, 2, 3, 4, 5, 5, 6, 3, 10]) | |
assert_equal 63, score_game([1, 2, 3, 4, 5, 5, 6, 3, 10, 9]) | |
assert_equal 65, score_game([1, 2, 3, 4, 5, 5, 6, 3, 10, 9, 1]) | |
assert_equal 75, score_game([1, 2, 3, 4, 5, 5, 6, 3, 10, 9, 1, 5]) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Common Lisp version is here.