Permalink
Browse files

Kata de Enero StringCalculator en PHP5.3

  • Loading branch information...
1 parent ca2f561 commit 11441864657d6fe6320166be2d875076e8ba2a61 minaya committed Sep 23, 2011
@@ -0,0 +1,18 @@
+<?php
+class StringCalculator
+{
+ private $stringParser;
+
+ public function __construct(StringParser $stringParser)
+ {
+ $this->stringParser = $stringParser;
+ }
+
+ public function add($stringNumbers)
+ {
+ if($stringNumbers == "")
+ return 0;
+
+ return array_sum($this->stringParser->parse($stringNumbers));
+ }
+}
@@ -0,0 +1,74 @@
+<?php
+class StringParser
+{
+ const NEW_LINE = "\n";
+ const DEFAULT_DELIMITERS = "\n,";
+ const DEFINE_DELIMITER_LINE = "//";
+ const INIT_DEFINE_DELIMITER = "[";
+ const END_DEFINE_DELIMITER = "]";
+
+ private $delimiters;
+
+
+ public function __construct()
+ {
+ $this->delimiters = self::DEFAULT_DELIMITERS;
+ }
+
+ public function parse($string)
+ {
+ // Se comprueba si la primera línea es de definición de delimitador
+ if($this->checkIfExistsCustomDelimiter($string))
+ {
+ $this->delimiters = $this->recoverCustomDelimiters($string);
+ $string = $this->removeCustomDelimitatorDefinition($string);
+ }
+
+ return $this->removeGreaterThan1000($this->checkNegatives(preg_split('/' . self::INIT_DEFINE_DELIMITER . $this->delimiters . self::END_DEFINE_DELIMITER . '/', $string)));
+ }
+
+ protected function recoverCustomDelimiters($string)
+ {
+ $customDelimiter = substr($string, 2, 1);
+
+ if($customDelimiter != self::INIT_DEFINE_DELIMITER)
+ return $customDelimiter;
+
+ $customDelimiter = '';
+ while(substr($string, 0, 1) != self::NEW_LINE)
+ {
+ $delimiterInit = strpos($string, self::INIT_DEFINE_DELIMITER);
+ $delimiterFinish = strpos($string, self::END_DEFINE_DELIMITER);
+ $delimiterLength = $delimiterFinish - $delimiterInit - 1;
+
+ $customDelimiter .= substr($string, $delimiterInit + 1, $delimiterLength);
+ $string = substr($string, $delimiterFinish + 1);
+ }
+
+ return $customDelimiter;
+ }
+
+ protected function checkIfExistsCustomDelimiter($string)
+ {
+ return substr($string, 0, 2) == self::DEFINE_DELIMITER_LINE;
+ }
+
+ protected function removeCustomDelimitatorDefinition($string)
+ {
+ return substr($string, strpos($string, self::NEW_LINE));
+ }
+
+ protected function checkNegatives($arrayNumbers)
+ {
+ $arrayNegatives = array_filter($arrayNumbers, function ($element) { return $element < 0; });
+ if(count($arrayNegatives) > 0)
+ throw new InvalidArgumentException('negatives not allowed -> ' . implode(', ', $arrayNegatives));
+
+ return $arrayNumbers;
+ }
+
+ protected function removeGreaterThan1000($arrayNumbers)
+ {
+ return array_values(array_filter($arrayNumbers, function ($element) { return $element <= 1000; }));
+ }
+}
@@ -0,0 +1,108 @@
+<?php
+require_once 'PHPUnit/Autoload.php';
+require_once 'src/StringCalculator.php';
+
+class StringCalculatorTest extends PHPUnit_Framework_TestCase
+{
+ private $stringCalculator;
+
+
+ public function SetUp()
+ {
+ $this->stringCalculator = new StringCalculator(new StringParser());
+ }
+
+ public function testFramework()
+ {
+ $this->assertTrue(true);
+ }
+
+ public function testEmptyStringShouldBeZero()
+ {
+ $this->assertEquals('0', $this->stringCalculator->add(''));
+ }
+
+ public function testAddOneNumberShouldBeTheNumber()
+ {
+ $this->assertEquals('0', $this->stringCalculator->add('0'));
+ $this->assertEquals('1', $this->stringCalculator->add('1'));
+ $this->assertEquals('53', $this->stringCalculator->add('53'));
+ }
+
+ public function testAddTwoNumbersShouldBeTheSumOfTheNumbers()
+ {
+ $this->assertEquals('1', $this->stringCalculator->add('0,1'));
+ $this->assertEquals('3', $this->stringCalculator->add('1,2'));
+ $this->assertEquals('100', $this->stringCalculator->add('53,47'));
+ }
+
+ public function testAddThreeNumbersShouldBeTheSumOfTheNumbers()
+ {
+ $this->assertEquals('3', $this->stringCalculator->add('0,1,2'));
+ $this->assertEquals('11', $this->stringCalculator->add('1,2,8'));
+ $this->assertEquals('105', $this->stringCalculator->add('53,47,5'));
+ }
+
+ public function testAddUnknowAmountOfNumbersShouldBeTheSumOfTheNumbers()
+ {
+ $this->assertEquals('10', $this->stringCalculator->add('0,1,2,5,2'));
+ $this->assertEquals('130', $this->stringCalculator->add('1,2,8,34,23,2,55,1,4'));
+ $this->assertEquals('188', $this->stringCalculator->add('53,47,5,1,4,6,33,6,33'));
+ }
+
+ public function testHandleNewLinesOrCommasAsSeparators()
+ {
+ $this->assertEquals('6', $this->stringCalculator->add("1\n2,3"));
+ $this->assertEquals('15', $this->stringCalculator->add("1\n2,3,7\n2"));
+ $this->assertEquals('96', $this->stringCalculator->add("54,2\n5,7\n9\n11,8"));
+ }
+
+ public function testAddNumbersWithCustomDelimiter()
+ {
+ $this->assertEquals('3', $this->stringCalculator->add("//;\n1;2"));
+ $this->assertEquals('15', $this->stringCalculator->add("//|\n1|2|12"));
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ * @expectedExceptionMessage negatives not allowed -> -2
+ */
+ public function testExceptionIfAddNegativeNumbers()
+ {
+ $this->stringCalculator->add('1,-2');
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ * @expectedExceptionMessage negatives not allowed -> -2, -5, -8, -6, -6
+ */
+ public function testExceptionIfAddSeveralNegativeNumbers()
+ {
+ $this->stringCalculator->add('1,-2,-5,6,-8,-6,-6');
+ $this->stringCalculator->add('//|\n1|-2|-5|6|-8|-6|-6');
+ }
+
+ public function testNumbersBiggerThan1000ShouldBeIgnored()
+ {
+ $this->assertEquals('2', $this->stringCalculator->add('2,1001'));
+ $this->assertEquals('10', $this->stringCalculator->add("//;\n2;1001;8"));
+ }
+
+ public function testDelimitersCouldBeAnyLength()
+ {
+ $this->assertEquals('6', $this->stringCalculator->add("//[***]\n1***2***3"));
+ }
+
+ public function testDelimitersCouldBeMultiple()
+ {
+ $this->assertEquals('6', $this->stringCalculator->add("//[*][%]\n1*2%3"));
+ $this->assertEquals('6', $this->stringCalculator->add("//[*][%]\n1*2%3*1001"));
+ $this->assertEquals('8', $this->stringCalculator->add("//[*][%]\n1*2%1001%3*2"));
+ }
+
+ public function testDelimitatorsWithAnyLengthCouldBeMultiple()
+ {
+ $this->assertEquals('8', $this->stringCalculator->add("//[**][%]\n1**2%1001%3**2"));
+ $this->assertEquals('8', $this->stringCalculator->add("//[*][%%%]\n1*2%%%1001%%%3*2"));
+ }
+}
@@ -0,0 +1,78 @@
+<?php
+require_once 'PHPUnit/Autoload.php';
+require_once 'src/StringParser.php';
+
+class StringParserTest extends PHPUnit_Framework_TestCase
+{
+ private $stringParser;
+
+
+ public function SetUp()
+ {
+ $this->stringParser = new StringParser();
+ }
+
+ public function testFramework()
+ {
+ $this->assertTrue(true);
+ }
+
+ public function testDescomposeNumbersSeparatedWithLines()
+ {
+ $this->assertEquals(array('1','2','3'), $this->stringParser->parse("1\n2,3"));
+ $this->assertEquals(array('54','2','5', '7','9','11','8'), $this->stringParser->parse("54,2\n5,7\n9\n11,8"));
+ }
+
+ public function testDescomposeNumbersWithCustomDelimiter()
+ {
+ $this->assertEquals(array('1','2'), $this->stringParser->parse("//;\n1;2"));
+ $this->assertEquals(array('1','2','8'), $this->stringParser->parse("//;\n1;2;8"));
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ * @expectedExceptionMessage negatives not allowed -> -2
+ */
+ public function testExceptionIfAddNegativeNumbers()
+ {
+ $this->stringParser->parse('1,-2');
+ }
+
+ /**
+ * HELPER TESTS for development. No need anymore.
+ */
+/*
+ public function testCheckNegatives()
+ {
+ $this->assertEquals(array('1','2'), $this->stringParser->checkNegatives(array('1','2')));
+ $this->assertEquals(array('1','1001', '8'), $this->stringParser->checkNegatives(array('1','1001', '8')));
+ }
+
+ /**
+ * @expectedException InvalidArgumentException
+ * @expectedExceptionMessage negatives not allowed -> -2
+ */
+/*
+ public function testCheckNegativesException()
+ {
+ $this->stringParser->checkNegatives(array('1','-2'));
+ }
+
+ public function testRemoveGreatherThan1000()
+ {
+ $this->assertEquals(array('2'), $this->stringParser->removeGreaterThan1000(array('2', '1001')));
+ $this->assertEquals(array('2','8'), $this->stringParser->removeGreaterThan1000(array('2', '1001', '8')));
+ $this->assertEquals(array('2','8'), $this->stringParser->parse("//;\n2;1001;8"));
+ }
+
+ public function testDelimitersCouldBeAnyLength()
+ {
+ $this->assertEquals('***', $this->stringParser->recoverCustomDelimiters("//[***]\n1***2***3"));
+ }
+
+ public function testDelimitersCouldBeMultiple()
+ {
+ $this->assertEquals('*%', $this->stringParser->recoverCustomDelimiters("//[*][%]\n1*2%3"));
+ }
+*/
+}

0 comments on commit 1144186

Please sign in to comment.