From 44a3ef971dbd7aa7396078f24094f3d13dbe798c Mon Sep 17 00:00:00 2001 From: Oliver Davies Date: Sat, 4 Jul 2020 08:27:45 +0100 Subject: [PATCH] Roman numeral converter --- composer.json | 3 ++ composer.lock | 67 +++++++++++++++++++++++++++- src/RomanNumeralsConverter.php | 50 +++++++++++++++++++++ tests/RomanNumeralsConverterTest.php | 40 +++++++++++++++++ 4 files changed, 158 insertions(+), 2 deletions(-) create mode 100644 src/RomanNumeralsConverter.php create mode 100644 tests/RomanNumeralsConverterTest.php diff --git a/composer.json b/composer.json index cad6a59..334bc26 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,9 @@ { "minimum-stability": "dev", "prefer-stable": true, + "require": { + "beberlei/assert": "^3.2" + }, "require-dev": { "pestphp/pest": "^0.2.3", "phpunit/phpunit": "^9.0" diff --git a/composer.lock b/composer.lock index 7756a38..d821cc4 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,71 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "bfb10a7a41c18e92587c515155e29ab5", - "packages": [], + "content-hash": "aebfcacf1a8ee688656954bd83cb1c5b", + "packages": [ + { + "name": "beberlei/assert", + "version": "v3.2.7", + "source": { + "type": "git", + "url": "https://github.com/beberlei/assert.git", + "reference": "d63a6943fc4fd1a2aedb65994e3548715105abcf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/beberlei/assert/zipball/d63a6943fc4fd1a2aedb65994e3548715105abcf", + "reference": "d63a6943fc4fd1a2aedb65994e3548715105abcf", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-json": "*", + "ext-mbstring": "*", + "ext-simplexml": "*", + "php": "^7" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "*", + "phpstan/phpstan-shim": "*", + "phpunit/phpunit": ">=6.0.0 <8" + }, + "suggest": { + "ext-intl": "Needed to allow Assertion::count(), Assertion::isCountable(), Assertion::minCount(), and Assertion::maxCount() to operate on ResourceBundles" + }, + "type": "library", + "autoload": { + "psr-4": { + "Assert\\": "lib/Assert" + }, + "files": [ + "lib/Assert/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-2-Clause" + ], + "authors": [ + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de", + "role": "Lead Developer" + }, + { + "name": "Richard Quadling", + "email": "rquadling@gmail.com", + "role": "Collaborator" + } + ], + "description": "Thin assertion library for input validation in business models.", + "keywords": [ + "assert", + "assertion", + "validation" + ], + "time": "2019-12-19T17:51:41+00:00" + } + ], "packages-dev": [ { "name": "doctrine/instantiator", diff --git a/src/RomanNumeralsConverter.php b/src/RomanNumeralsConverter.php new file mode 100644 index 0000000..07eabe4 --- /dev/null +++ b/src/RomanNumeralsConverter.php @@ -0,0 +1,50 @@ + 'M', + 900 => 'CM', + 500 => 'D', + 400 => 'CD', + 100 => 'C', + 90 => 'XC', + 50 => 'L', + 40 => 'XL', + 10 => 'X', + 9 => 'IX', + 5 => 'V', + 4 => 'IV', + 3 => 'III', + 2 => 'II', + 1 => 'I', + ]; + + public static function convert(int $input): string + { + Assert::that($input) + ->greaterOrEqualThan(0, 'Cannot convert negative numbers'); + + $letters = ''; + + while ($input > 0) { + foreach (static::$map as $number => $letter) { + if ($input >= $number) { + // Add the appropriate numeral and reduce the value of + // $input accordingly. + $letters .= $letter; + $input = ($input - $number); + break; + } + } + } + + return $letters; + } +} diff --git a/tests/RomanNumeralsConverterTest.php b/tests/RomanNumeralsConverterTest.php new file mode 100644 index 0000000..d09785a --- /dev/null +++ b/tests/RomanNumeralsConverterTest.php @@ -0,0 +1,40 @@ +with([ + [1, 'I'], + [2, 'II'], + [3, 'III'], + [4, 'IV'], + [5, 'V'], + [9, 'IX'], + [10, 'X'], + [15, 'XV'], + [19, 'XIX'], + [20, 'XX'], + [21, 'XXI'], + [40, 'XL'], + [50, 'L'], + [80, 'LXXX'], + [90, 'XC'], + [100, 'C'], + [110, 'CX'], + [400, 'CD'], + [500, 'D'], + [700, 'DCC'], + [900, 'CM'], + [1000, 'M'], + [1986, 'MCMLXXXVI'], + [1990, 'MCMXC'], + [2020, 'MMXX'], +]); + +it('cannot convert negative numbers', function (): void { + RomanNumeralsConverter::convert(-1); +})->throws(AssertionFailedException::class, 'Cannot convert negative numbers');