Skip to content

Instantly share code, notes, and snippets.

@alberto
Created January 4, 2011 19:26
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 alberto/765257 to your computer and use it in GitHub Desktop.
Save alberto/765257 to your computer and use it in GitHub Desktop.
String Calculator Kata
require "test_notifier/runner/rspec"
TestNotifier.default_notifier = :notify_send
RSpec::Matchers.define :add_to do |expected|
match do |string|
string.add == expected
end
end
module AddableString
def add
numbers.inject(0) { |sum, number| sum + number }
end
private
def numbers
split(any_delimiter).map(&:to_i)
end
def any_delimiter
Regexp.union delimiters
end
def delimiters
return default_delimiters + singlechar_delimiter + bracketed_delimiters
end
def default_delimiters
[",", "\n"]
end
def singlechar_delimiter
has_custom_delimiters?? [self[2]] : []
end
def bracketed_delimiters
scan(/\[(.+?)\]/).map{ |m| m[0] }
end
def has_custom_delimiters?
start_with?("//")
end
end
class String
include AddableString
end
describe "String Calculator" do
it "should return 0 for ''" do
"".should add_to 0
end
context "can add one number" do
it "should return 1 for 1" do
"1".should add_to 1
end
it "should return 2 for 2" do
"2".should add_to 2
end
it "should return 42 for 42" do
"42".should add_to 42
end
end
context "can add two numbers" do
it "should return 2 for 1,1" do
"1,1".should add_to 2
end
it "should return 3 for 1,2" do
"1,2".should add_to 3
end
it "should return 12 for 1,11" do
"1,11".should add_to 12
end
end
context "can add any amount of numbers" do
it "should return 6 for 1,2,3" do
"1,2,3".should add_to 6
end
it "should return 200 for one-hundred twos" do
Array.new(2,100).join(',').should add_to 200
end
end
context "delimiters" do
it "supports \n as delimiter" do
"1\n2".should add_to 3
end
it "supports ; as delimiter" do
"//;\n1;2".should add_to 3
end
it "supports % as delimiter" do
"//%\n1%2".should add_to 3
end
context "delimiters of any length" do
it "supports ;: as delimiter" do
"//[;:]\n1;:2".should add_to 3
end
it "supports ::: as delimiter" do
"//[:::]\n1:::2".should add_to 3
end
end
context "multiple delimiters" do
it "supports %, & as delimiters" do
"//[%][&]\n1%2&3".should add_to 6
end
end
end
end
@plagelao
Copy link

plagelao commented Jan 5, 2011

Yo estoy abriendo la clase String directamente :P

class String
  def add
    ...
  end
end

Eso hace que cambie bastante el código. Mañana intento subir un gist :)

@alberto
Copy link
Author

alberto commented Jan 5, 2011

sí, ayer lo pensé mientras hacía la kata, pero decidí dejarlo para hoy :)

@xaviuzz
Copy link

xaviuzz commented Jan 6, 2011

El inject ya es bastante feo y poco semantico en su forma
def add
summands.inject { |sum, summand| sum + summand }
end
asi que cuando no necesites un valor inicial distinto del valor del primer elemento intenta no ofuscar hombre!! :)
mira que me parece feo el inject .. no hay alternativas mas semanticas??

@xaviuzz
Copy link

xaviuzz commented Jan 6, 2011

ahh y quiza podrias reforzar la prueba en el contexto an unknown amount of numbers

@alberto
Copy link
Author

alberto commented Jan 6, 2011

Sobre el inject, parece que no funciona sin el (0), ¿puede que porque summand es un string intente inicializar sum="" ? La verdad es que hasta hace 2 días que me lo comentó plagelao no lo conocía. No conozco nada mejor, tampoco me gusta mucho la semántica esa.

Sobre reforzar ese contexto, ¿qué echas en falta?

@alberto
Copy link
Author

alberto commented Jan 7, 2011

@xaviuzz el add que proponías devuelve nil en vez de 0 cuando summands == []

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