Page Menu
Home
DevCentral
Search
Configure Global Search
Log In
Files
F3751655
D1599.id4081.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
4 KB
Referenced Files
None
Subscribers
None
D1599.id4081.diff
View Options
diff --git a/src/Culture/Rome/RomanNumerals.php b/src/Culture/Rome/RomanNumerals.php
new file mode 100644
--- /dev/null
+++ b/src/Culture/Rome/RomanNumerals.php
@@ -0,0 +1,99 @@
+<?php
+declare(strict_types=1);
+
+namespace Keruald\OmniTools\Culture\Rome;
+
+use InvalidArgumentException;
+
+final class RomanNumerals {
+
+ public static function fromHinduArabic (int $number) : string {
+ self::assertStrictlyPositiveNumber($number);
+
+ $table = self::getHinduArabicTable();
+
+ return $table[$number] ?? self::computeFromHinduArabic($number);
+ }
+
+ /**
+ * Provides a canonical table with hindu arabic numerals as keys,
+ * and roman numerals as values.
+ */
+ public static function getHinduArabicTable () : array {
+ return [
+ 1 => 'i',
+ 2 => 'ii',
+ 3 => 'iii',
+ 4 => 'iv',
+ 5 => 'v',
+ 6 => 'vi',
+ 7 => 'vii',
+ 8 => 'viii',
+ 9 => 'ix',
+ 10 => 'x',
+ 50 => 'l',
+ 100 => 'c',
+ 500 => 'd',
+ 1000 => 'm',
+ ];
+ }
+
+ private static function getComputeHinduArabicTable () : iterable {
+ // limit => number to subtract (as a [roman, hindu arabic] array)
+ yield 21 => ['x', 10];
+ yield 30 => ['xx', 20];
+ yield 40 => ['xxx', 30];
+ yield 50 => ['xl', 40];
+ yield 60 => ['l', 50];
+ yield 70 => ['lx', 60];
+ yield 80 => ['lxx', 70];
+ yield 90 => ['lxxx', 80];
+ yield 100 => ['xc', 90];
+ yield 200 => ['c', 100];
+ yield 300 => ['cc', 200];
+ yield 400 => ['ccc', 300];
+ yield 500 => ['cd', 400];
+ yield 600 => ['d', 500];
+ yield 700 => ['dc', 600];
+ yield 800 => ['dcc', 700];
+ yield 900 => ['dccc', 800];
+ yield 1000 => ['cm', 900];
+ }
+
+ private static function computeFromHinduArabic (int $number) : string {
+ if ($number > 1000) {
+ return self::computeFromHinduArabicWithThousands($number);
+ }
+
+ foreach (self::getComputeHinduArabicTable() as $limit => $term) {
+ if ($number < $limit) {
+ return $term[0] .
+ self::fromHinduArabic($number - $term[1]);
+ }
+ }
+
+ throw new \LogicException("This should be unreachable code.");
+ }
+
+ private static function computeFromHinduArabicWithThousands (
+ int $number
+ ) : string {
+ $thousandsAmount = (int)floor($number / 1000);
+ $remainder = $number % 1000;
+
+ $roman = str_repeat('m', $thousandsAmount);
+ if ($remainder > 0) {
+ $roman .= self::fromHinduArabic($remainder);
+ }
+
+ return $roman;
+ }
+
+ private static function assertStrictlyPositiveNumber (int $number) : void {
+ if ($number < 1) {
+ throw new InvalidArgumentException(
+ "Can only convert strictly positive numbers"
+ );
+ }
+ }
+}
diff --git a/tests/Culture/Rome/RomanNumeralsTest.php b/tests/Culture/Rome/RomanNumeralsTest.php
new file mode 100644
--- /dev/null
+++ b/tests/Culture/Rome/RomanNumeralsTest.php
@@ -0,0 +1,43 @@
+<?php
+declare(strict_types=1);
+
+namespace Keruald\OmniTools\Tests\Culture\Rome;
+
+use Keruald\OmniTools\Culture\Rome\RomanNumerals;
+use PHPUnit\Framework\TestCase;
+use InvalidArgumentException;
+
+class RomanNumeralsTest extends TestCase {
+
+ /**
+ * @dataProvider provideRomanAndHinduArabicNumerals
+ */
+ public function testFromHindiArabicNumeral (
+ string $roman,
+ int $hinduArabic
+ ) : void {
+ $this->assertEquals(
+ $roman,
+ RomanNumerals::fromHinduArabic($hinduArabic)
+ );
+ }
+
+ public function provideRomanAndHinduArabicNumerals () : iterable {
+ yield ['i', 1];
+ yield ['xi', 11];
+ yield ['xlii', 42];
+ yield ['mcmxcix', 1999];
+ yield ['mm', 2000];
+ }
+
+ public function testFromHindiArabicNumeralWithNegativeNumbers () : void {
+ $this->expectException(InvalidArgumentException::class);
+ RomanNumerals::fromHinduArabic(-1);
+ }
+
+ public function testFromHindiArabicNumeralWithZero () : void {
+ $this->expectException(InvalidArgumentException::class);
+ RomanNumerals::fromHinduArabic(0);
+ }
+
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Nov 18, 11:29 (22 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2250592
Default Alt Text
D1599.id4081.diff (4 KB)
Attached To
Mode
D1599: Add a hindu arabic to roman numerals converter
Attached
Detach File
Event Timeline
Log In to Comment