This is my solution of string calulator kata in scala(i'm new of tdd). I'd like a general review of this.
String Calculator
Create a simple String calculator with a method int Add(string numbers) The method can take 0, 1 or 2 numbers, and will return their sum (for an empty string it will return 0) for example “” or “1” or “1,2”
-Allow the Add method to handle an unknown amount of numbers
-Allow the Add method to handle new lines between numbers (instead of commas). the following input is ok: “1\n2,3” (will equal 6) the following input is NOT ok: “1,\n” (not need to prove it - just clarifying)
-Support different delimiters to change a delimiter, the beginning of the string will contain a separate line that looks like this:
“//[delimiter]\n[numbers…]” for example “//;\n1;2” should return three where the default delimiter is ‘;’ .-Numbers bigger than 1000 should be ignored, so adding 2 + 1001 = 2
-Delimiters can be of any length with the following format: “//[delimiter]\n” for example: “//[***]\n1***2***3” should return 6
package stringcalculator
import org.scalatest.{BeforeAndAfter, FunSuite}
class StringCalculetor3 extends FunSuite with BeforeAndAfter {
private val calculator = new Calculator(new InputParser())
before {}
test("sum of empty string is 0") {
assert(0 === sum(""))
}
test("sum of one number string is number") {
assert(5 === sum("5"))
assert(6 === sum("6"))
}
test("sum of two numbers separated with comma") {
assert(3 === sum("1,2"))
assert(5 === sum("1,4"))
}
test("sum of 3 numbers separated with comma") {
assert(6 === sum("1,2,3"))
}
test("sum of 2 numbers separated new line separetor") {
assert(3 === sum("1\n2"))
assert(6 === sum("1\n2,3"))
}
test("sum of 2 numbers with another separator") {
assert(3 === sum("//;\n1;2"))
}
test("sum of 2 numbers with multiple separator") {
assert(3 === sum("//[;]\n1;2"))
assert(3 === sum("//[--]\n1--2"))
}
test("numbers > 1000 do not fall in the sum") {
assert(3 === sum("1,2,1001"))
}
private def sum(in: String): Int = {
calculator.sum(in)
}
The calculator
package stringcalculator
/**
* Created by MarcopTo on 20/10/2015.
*/
class Calculator(inputParser: InputParser) {
def sum(input: String): Int = {
val (in, separetor) = inputParser.parse(input)
val numbers = in.split(separetor).map(_.toInt).filter(_ < 1001)
numbers.sum
}
}
The parser
package stringcalculator
/**
* Created by MarcopTo on 20/10/2015.
*/
class InputParser() {
private val defaultSeparator: String = ",|\n"
private val singleSeparatorPosition: Int = 2
def parse(input: String): (String, String) =
if (containsSeparator(input)) {
val endOfHeader: Int = input.indexOf("\n")
val separetor = extractSeparator(input,endOfHeader)
val in = extractInput(input,endOfHeader)
(in, separetor)
}else
(defaultInput(input), defaultSeparator)
private def defaultInput(input: String): String = if (input.isEmpty) "0" else input
private def containsSeparator(in: String): Boolean = in.contains("//")
private def extractInput(input: String,endOfHeader: Int): String = input.substring(endOfHeader+1)
private def extractSeparator(in: String,endOfHeader: Int): String = {
val header = getHeader(in, endOfHeader)
if (containsMultipleSeparator(header))
in.substring(in.indexOf("[") + 1, in.indexOf("]"))
else
header.charAt(singleSeparatorPosition).toString
}
private def getHeader(in: String, endOfHeader: Int): String = in.substring(0, endOfHeader)
private def containsMultipleSeparator(in: String): Boolean = in.contains("[")
}