Skip to content

Instantly share code, notes, and snippets.

@bjjb
Created June 28, 2018 17:33
Show Gist options
  • Save bjjb/80fccd24ba87c3352bf8ec30fa4e6e90 to your computer and use it in GitHub Desktop.
Save bjjb/80fccd24ba87c3352bf8ec30fa4e6e90 to your computer and use it in GitHub Desktop.
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
@bjjb
Copy link
Author

bjjb commented Jun 28, 2018

Common Lisp version is here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment