Skip to content

Instantly share code, notes, and snippets.

@marksim
Created June 18, 2013 03:16
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 marksim/5802445 to your computer and use it in GitHub Desktop.
Save marksim/5802445 to your computer and use it in GitHub Desktop.
String Calculator Pairing Kata with @shicholas
require 'rspec'
class StringCalculator
def initialize(string)
@string = string
end
def call
raise NoNegativesAllowed.new(numbers.select{|n| n < 0}) if numbers.any? {|n| n < 0}
numbers.inject(&:+).to_i
end
def delimiter
if @string.start_with?("//")
parts = @string.split("\n", 2)
parts.first.sub("//", "")
else
","
end
end
def string
if @string.start_with?("//")
parts = @string.split("\n", 2)
parts.last
else
@string
end
end
def numbers
string.split(Regexp.new("[\n#{delimiter}]")).map(&:to_i)
end
end
class NoNegativesAllowed < Exception
def initialize(*args)
@bad_numbers = args
end
def message
"No Negatives Allowed: #{@bad_numbers.join(", ")}"
end
end
class String
def calc
StringCalculator.new(self).call
end
end
describe "StringCalculator" do
it "returns zero for the empty string" do
expect("".calc).to eql(0)
end
it "returns 1 for '1'" do
expect("1".calc).to eql(1)
end
it "returns 3 for '1,2'" do
expect("1,2".calc).to eql(3)
end
it "returns 5 for '1,2,2'" do
expect("1,2,2".calc).to eql(5)
end
it "allows for new lines" do
expect("1\n2,3".calc).to eql(6)
end
it "allows you to specify a delmiter" do
expect("//;\n1;2".calc).to eql(3)
end
it "throws an error with negative numbers" do
expect { "1,-2".calc }.to raise_error(NoNegativesAllowed)
end
it "shows negative numbers with NoNegativesAllowed" do
begin
"1,-2,-3".calc
rescue NoNegativesAllowed => nna
expect(nna.message).to eql("No Negatives Allowed: -2, -3")
end
end
end
@shicholas
Copy link

Here's our example with refinements

module StringCalculator
  refine String do 

    def calc
      raise NoNegativeNumbers.new(negative_numbers) if negative_numbers?
      numbers.inject(:+).to_i
    end

    private

    def delimiter
      if self.start_with?('//')
        parts = self.split("\n", 2)
        parts.first.sub('//', '')
      else
        /[\n,]/
      end
    end

    def numbers
      if self.start_with?("//")
        parts = self.split("\n", 2)
        parts.last.split(delimiter).map(&:to_i)
      else
        self.split(delimiter).map(&:to_i)
      end
    end

    def negative_numbers
      numbers.select{|n| n < 0}
    end

    def negative_numbers?
      numbers.any? {|n| n < 0} ? true : false
    end

  end
end

class NoNegativeNumbers < Exception

  def initialize(*args)
    @negative_numbers = args
  end

  def message
    "No negative numbers allowed: #{@negative_numbers.join(', ')}"
  end
end

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