Last active
December 23, 2015 07:49
-
-
Save kevbuchanan/6603426 to your computer and use it in GitHub Desktop.
From Ruby Quiz: http://rubyquiz.strd6.com/quizzes/181-bowling-scores
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
class Frame | |
attr_reader :rolls | |
def initialize(rolls) | |
@rolls = rolls.first == 10 ? [rolls.first] : rolls | |
end | |
def roll_score | |
@rolls.inject(:+) | |
end | |
def spare? | |
roll_score == 10 && !strike? | |
end | |
def strike? | |
@rolls.first == 10 | |
end | |
def bonus_rolls | |
if strike? | |
2 | |
elsif spare? | |
1 | |
else | |
0 | |
end | |
end | |
def first_roll | |
if strike? | |
"X" | |
elsif @rolls.first == 0 | |
"-" | |
else | |
@rolls.first.to_s | |
end | |
end | |
def last_roll | |
if strike? | |
"" | |
elsif spare? | |
"/" | |
elsif @rolls.last == 0 | |
"-" | |
else | |
@rolls.last.to_s | |
end | |
end | |
end | |
class Scorecard | |
attr_reader :bowler | |
def initialize(input) | |
@bowler = input.split(' ')[0] | |
@rolls = input.split(' ')[1..-1].map(&:to_i) | |
@frames = generate_frames | |
end | |
def total_score | |
(0..9).inject(0) do |score, index| | |
score += score_for(index) | |
end | |
end | |
def score_for(frame_index) | |
frame = @frames[frame_index] | |
next_frames_rolls = [] | |
next_frames_rolls += @frames[frame_index + 1].rolls unless @frames[frame_index + 1].nil? | |
next_frames_rolls += @frames[frame_index + 2].rolls unless @frames[frame_index + 2].nil? | |
extra_score = next_frames_rolls.shift(frame.bonus_rolls).inject(:+) || 0 | |
frame.roll_score + extra_score | |
end | |
def generate_frames | |
frames = [] | |
new_rolls = @rolls.join(' ').gsub('10', '10 0').split(' ').map(&:to_i) | |
new_rolls.each_slice(2) do |frame| | |
frames << Frame.new(frame) | |
end | |
frames | |
end | |
def print_scorecard | |
puts "#{@bowler}'s score: #{total_score}" | |
puts "Frame Roll Roll Score" | |
@frames.each_with_index do |frame, index| | |
puts "#{index + 1} #{frame.first_roll} #{frame.last_roll} #{score_for(index)}" | |
end | |
end | |
end | |
scorecard = Scorecard.new('John 6 2 7 1 10 9 0 8 2 10 10 3 5 7 2 5 5 8') | |
scorecard.print_scorecard |
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 'rspec' | |
require 'shoulda' | |
require_relative "bowling" | |
describe Frame do | |
let(:frame) { Frame.new([0,9]) } | |
let(:other_frame) { Frame.new([5,0]) } | |
let(:strike_frame) { Frame.new([10, 0]) } | |
let(:spare_frame) { Frame.new([7, 3]) } | |
it 'should have a rolls array' do | |
expect(frame.rolls).to eq([0,9]) | |
end | |
it 'should remove the 0 roll from a strike roll' do | |
expect(strike_frame.rolls).to eq([10]) | |
end | |
describe '#roll_score' do | |
it 'should return the sum of the two rolls' do | |
expect(frame.roll_score).to eq(9) | |
end | |
end | |
describe '#spare?' do | |
context 'a spare' do | |
it 'should return true' do | |
expect(spare_frame.spare?).to be_true | |
end | |
end | |
context 'not a spare' do | |
it 'should return false' do | |
expect(frame.spare?).to be_false | |
end | |
end | |
end | |
describe '#strike?' do | |
context 'a strike' do | |
it 'should return true' do | |
expect(strike_frame.strike?).to be_true | |
end | |
end | |
context 'not a strike' do | |
it 'should return false' do | |
expect(frame.strike?).to be_false | |
end | |
end | |
end | |
describe '#bonus_rolls' do | |
context 'a strike' do | |
it 'should return 2' do | |
expect(strike_frame.bonus_rolls).to eq(2) | |
end | |
end | |
context 'a spare' do | |
it 'should return 1' do | |
expect(spare_frame.bonus_rolls).to eq(1) | |
end | |
end | |
context 'not a spare or strike' do | |
it 'should return 0' do | |
expect(frame.bonus_rolls).to eq(0) | |
end | |
end | |
end | |
describe '#first_roll' do | |
context 'a strike' do | |
it 'should return a X' do | |
expect(strike_frame.first_roll).to eq('X') | |
end | |
end | |
context 'a zero' do | |
it 'should return a -' do | |
expect(frame.first_roll).to eq('-') | |
end | |
end | |
context 'any other roll' do | |
it 'should return the number' do | |
expect(spare_frame.first_roll).to eq('7') | |
end | |
end | |
end | |
describe '#last_roll' do | |
context 'a strike' do | |
it 'should return an empty string' do | |
expect(strike_frame.last_roll).to eq('') | |
end | |
end | |
context 'a spare' do | |
it 'should return a /' do | |
expect(spare_frame.last_roll).to eq('/') | |
end | |
end | |
context 'a zero' do | |
it 'should return a -' do | |
expect(other_frame.last_roll).to eq('-') | |
end | |
end | |
context 'any other roll' do | |
it 'should return the number' do | |
expect(frame.last_roll).to eq('9') | |
end | |
end | |
end | |
end | |
describe Scorecard do | |
let(:perfect_game) { Scorecard.new('Kevin 10 10 10 10 10 10 10 10 10 10 10 10')} | |
it 'has a bowler name' do | |
expect(perfect_game.bowler).to eq('Kevin') | |
end | |
describe '#total_score' do | |
it 'returns the correct score' do | |
expect(perfect_game.total_score).to eq(300) | |
end | |
end | |
describe '#score_for' do | |
it 'return the correct score for the given frame' do | |
expect(perfect_game.score_for(1)).to eq(30) | |
end | |
end | |
describe '#generate_frames' do | |
it 'returns an array of frames' do | |
expect(perfect_game.generate_frames.first).to be_a(Frame) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment