Skip to content

Instantly share code, notes, and snippets.

@rwarbelow
Last active August 29, 2015 13:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rwarbelow/9043310 to your computer and use it in GitHub Desktop.
Save rwarbelow/9043310 to your computer and use it in GitHub Desktop.
Kata
class StringCalculator
def initialize(numbers)
@numbers = numbers
check_validity!
end
def add
integers.reduce(0, :+)
end
def delimeter
if match = numbers.match(%r(//(.*)\n))
match[1]
else
/\n|,/
end
end
private
attr_reader :numbers
def check_validity!
delimeters = numbers.scan(delimeter)
raise if delimeters.count > integers.count
negatives = integers.select { |num| num < 0 }
raise(ArgumentError, "negatives not allowed: #{negatives.join(", ")}") if negatives.any?
end
def all_numbers
numbers.split(delimeter).map(&:to_i)
end
def integers
all_numbers.reject(&:zero?).reject {|num| num > 1000 }
end
end
require 'rspec'
require_relative 'string_calculator'
describe StringCalculator do
let(:calculator) { StringCalculator }
it 'returns 0 when input is an empty string' do
expect(calculator.new("").add).to eq(0)
end
it 'returns the number passed in for a single number' do
expect(calculator.new('1').add).to eq(1)
end
it 'returns sum of two comma-separated numbers' do
expect(calculator.new('1,2').add).to eq(3)
end
it 'returns the sum of any number of numbers' do
expect(calculator.new('1,5,6,7').add).to eq(19)
end
it 'returns the sum of numbers separated by new lines or commas' do
expect(calculator.new("1\n2,3").add).to eq(6)
end
it 'does not allow two adjacent delimeters' do
expect { calculator.add("1,\n") }.to raise_error
end
it 'works for multi-digit numbers' do
expect(calculator.new('13,14,15').add).to eq(42)
end
describe 'delimeter definition' do
it 'is defined by //<delimeter>\n' do
expect(calculator.new("//&\n1&2&3").delimeter).to eq('&')
end
it 'uses its new delimeter for calculating sums' do
expect(calculator.new("//&\n1&2&3").add).to eq(6)
end
it 'raises an exception when two or more delimeters are adjacent' do
expect { calculator.new("//&\n1&2&&&3").add }.to raise_error
end
it 'accepts delimeters of any length' do
expect(calculator.new("//*^\n1*^2*^3").add).to eq(6)
end
it 'allows multiple delimeters' do
expect(calculator.new("//[@][%]\n1@2%3").add).to eq(6)
end
end
describe 'negative numbers' do
it 'raises an exception' do
expect { calculator.new("1,-5").add }.to raise_error
end
it 'returns the number that raised the exception' do
expect { calculator.new("1,-5").add }.to raise_error(ArgumentError, "negatives not allowed: -5")
end
it 'returns all negative numbers that were included' do
expect { calculator.new("-1,-5").add }.to raise_error(ArgumentError, "negatives not allowed: -1, -5")
end
end
it 'ignores numbers larger than 1000' do
expect(calculator.new("2,1005").add).to eq(2)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment