January kata – String Calculator

My first kata I ever did was due to 12 meses 12 katas initiative (12 months 12 katas):

Un mes una kata, ¡mejora tu arte y compártelo con los demás! Ese es el objetivo principal de esta iniciativa que nace de una comunidad preocupada por mejorar sus habilidades y así crear software de más calidad.

Every month, one kata. Improve your coding skills and share them with others! This is the main objective of this initiative, that was conceived in a community striving to improve its skills and thus create better software.

The january kata was String Calculator. I implemented it in Scala with Scala Test. My solution is listed below. For the full source code, go to GitHub. I used this kata to start learning Scala. My progress was very slow: I was combining coding with reading (blog and books about Scala and functional programming).

import java.util.regex.Pattern.quote

class StringCalculator {
  private val defaultSeparators = """,|\n"""

  def sum(expression: String): Int = {
    val (separators, summands) = splitIntoSeparatorsAndSummands(expression)

    val numericSummands = (separators.r).split(summands).filter(_ != "").map(_.toInt)
    val negativeSummands = numericSummands.filter(_ < 0)
    if (negativeSummands.nonEmpty) throw new IllegalArgumentException(negativeSummands.mkString(","))
    numericSummands.filter(_ <= 1000) .foldLeft(0)((sum, summand) => {
      sum + summand
    })
  }

  private def splitIntoSeparatorsAndSummands(expression: String) = {
    val separatorsRegex = """//(.+)\n""".r
    (separatorsRegex findFirstMatchIn expression) match {
      case Some(separatorsMatch) => (convertFoundSeparatorsToRegex(separatorsMatch.group(1)), separatorsMatch.after.toString)
      case None => (defaultSeparators, expression)
    }
  }

  private def convertFoundSeparatorsToRegex(separators: String) = {
    val singleSeparatorRegex = """\[.+?\]""".r
    val quotedSeparators = for(sep <- singleSeparatorRegex findAllIn separators)
      yield quote(sep.replaceAll("""[\[\]]""", ""))

    quotedSeparators.mkString("|")
  }
}

Next task: Roman Numerals. This will be tough, because I’m biased: I saw an elegant solution a couple of weeks ago and it was broadly discussed in the Agile Spain group.

Advertisements