Created
January 8, 2020 21:20
-
-
Save laracasts/869863f60ae3554a1c740e7eb787e745 to your computer and use it in GitHub Desktop.
String Calculator Kata
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App; | |
use Exception; | |
class StringCalculator | |
{ | |
/** | |
* The maximum number allowed. | |
*/ | |
const MAX_NUMBER_ALLOWED = 1000; | |
/** | |
* The delimiter for the numbers. | |
* | |
* @var string | |
*/ | |
protected string $delimiter = ",|\n"; | |
/** | |
* Add the provided set of numbers. | |
* | |
* @param string $numbers | |
* @return int | |
* | |
* @throws \Exception | |
*/ | |
public function add(string $numbers) | |
{ | |
$this->disallowNegatives($numbers = $this->parseString($numbers)); | |
return array_sum( | |
$this->ignoreGreaterThan1000($numbers) | |
); | |
} | |
/** | |
* Parse the numbers string. | |
* | |
* @param string $numbers | |
* @return array | |
*/ | |
protected function parseString(string $numbers): array | |
{ | |
$customDelimiter = '\/\/(.)\n'; | |
if (preg_match("/{$customDelimiter}/", $numbers, $matches)) { | |
$this->delimiter = $matches[1]; | |
$numbers = str_replace($matches[0], '', $numbers); | |
} | |
return preg_split("/{$this->delimiter}/", $numbers); | |
} | |
/** | |
* Do not allow any negative numbers. | |
* | |
* @param array $numbers | |
* @throws Exception | |
*/ | |
protected function disallowNegatives(array $numbers): void | |
{ | |
foreach ($numbers as $number) { | |
if ($number < 0) { | |
throw new Exception('Negative numbers are disallowed.'); | |
} | |
} | |
} | |
/** | |
* Forget any number that is greater than 1,000. | |
* | |
* @param array $numbers | |
* @return array | |
*/ | |
protected function ignoreGreaterThan1000(array $numbers): array | |
{ | |
return array_filter( | |
$numbers, fn($number) => $number <= self::MAX_NUMBER_ALLOWED | |
); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
use App\StringCalculator; | |
use PHPUnit\Framework\TestCase; | |
class StringCalculatorTest extends TestCase | |
{ | |
/** @test */ | |
function it_evaluates_an_empty_string_as_0() | |
{ | |
$calculator = new StringCalculator(); | |
$this->assertSame(0, $calculator->add('')); | |
} | |
/** @test */ | |
function it_finds_the_sum_of_a_single_number() | |
{ | |
$calculator = new StringCalculator(); | |
$this->assertSame(5, $calculator->add('5')); | |
} | |
/** @test */ | |
function it_finds_the_sum_of_two_numbers() | |
{ | |
$calculator = new StringCalculator(); | |
$this->assertSame(10, $calculator->add('5,5')); | |
} | |
/** @test */ | |
function it_finds_the_sum_of_any_amount_of_numbers() | |
{ | |
$calculator = new StringCalculator(); | |
$this->assertSame(19, $calculator->add('5,5,5,4')); | |
} | |
/** @test */ | |
function it_accepts_a_new_line_character_as_a_delimiter_too() | |
{ | |
$calculator = new StringCalculator(); | |
$this->assertSame(10, $calculator->add("5\n5")); | |
} | |
/** @test */ | |
function negative_numbers_are_not_allowed() | |
{ | |
$calculator = new StringCalculator(); | |
$this->expectException(\Exception::class); | |
$calculator->add('5,-4'); | |
} | |
/** @test */ | |
function numbers_greater_than_1000_are_ignored() | |
{ | |
$calculator = new StringCalculator(); | |
$this->assertEquals(5, $calculator->add('5,1001')); | |
} | |
/** @test */ | |
function it_supports_custom_delimiters() | |
{ | |
$calculator = new StringCalculator(); | |
$this->assertEquals(20, $calculator->add("//:\n5:4:11")); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment