1 2 module roman; 3 4 /** 5 * Converts a roman number to an integer. 6 * Returns: the number as integer or 0 on invalid numbers. 7 */ 8 uint fromRoman(string str) pure nothrow @safe @nogc { 9 if(str.length) { 10 immutable two = str.length > 1; 11 if(str[0] == 'M') return 1000 + str[1..$].fromRoman; 12 else if(two && str[0..2] == "CM") return 900 + str[2..$].fromRoman; 13 else if(str[0] == 'D') return 500 + str[1..$].fromRoman; 14 else if(two && str[0..2] == "CD") return 400 + str[2..$].fromRoman; 15 else if(str[0] == 'C') return 100 + str[1..$].fromRoman; 16 else if(two && str[0..2] == "XC") return 90 + str[2..$].fromRoman; 17 else if(str[0] == 'L') return 50 + str[1..$].fromRoman; 18 else if(two && str[0..2] == "XL") return 40 + str[2..$].fromRoman; 19 else if(str[0] == 'X') return 10 + str[1..$].fromRoman; 20 else if(two && str[0..2] == "IX") return 9 + str[2..$].fromRoman; 21 else if(str[0] == 'V') return 5 + str[1..$].fromRoman; 22 else if(two && str[0..2] == "IV") return 4 + str[2..$].fromRoman; 23 else if(str[0] == 'I') return 1 + str[1..$].fromRoman; 24 } 25 return 0; 26 } 27 28 /// 29 pure nothrow @safe @nogc unittest { 30 31 assert(fromRoman("I") == 1); 32 assert(fromRoman("III") == 3); 33 assert(fromRoman("IV") == 4); 34 assert(fromRoman("V") == 5); 35 assert(fromRoman("XLI") == 41); 36 assert(fromRoman("MM") == 2000); 37 38 // invalids 39 assert(fromRoman("A") == 0); 40 41 } 42 43 /** 44 * Converts an integer to a roman number. 45 * Returns: A roman number or an empty string if the given number could not be converted. 46 */ 47 string toRoman(uint num) { 48 string ret = ""; 49 while (num >= 1000) { 50 ret ~= "M"; 51 num -= 1000; 52 } 53 while (num >= 900) { 54 ret ~= "CM"; 55 num -= 900; 56 } 57 while (num >= 500) { 58 ret ~= "D"; 59 num -= 500; 60 } 61 while (num >= 400) { 62 ret ~= "CD"; 63 num -= 400; 64 } 65 while (num >= 100) { 66 ret ~= "C"; 67 num -= 100; 68 } 69 while (num >= 90) { 70 ret ~= "XC"; 71 num -= 90; 72 } 73 while (num >= 50) { 74 ret ~= "L"; 75 num -= 50; 76 } 77 while (num >= 40) { 78 ret ~= "XL"; 79 num -= 40; 80 } 81 while (num >= 10) { 82 ret ~= "X"; 83 num -= 10; 84 } 85 while (num >= 9) { 86 ret ~= "IX"; 87 num -= 9; 88 } 89 while (num >= 5) { 90 ret ~= "V"; 91 num -= 5; 92 } 93 while (num >= 4) { 94 ret ~= "IV"; 95 num -= 4; 96 } 97 while (num >= 1) { 98 ret ~= "I"; 99 num -= 1; 100 } 101 return ret; 102 } 103 104 /// 105 unittest { 106 107 assert(toRoman(1) == "I"); 108 assert(toRoman(3) == "III"); 109 assert(toRoman(4) == "IV"); 110 assert(toRoman(5) == "V"); 111 assert(toRoman(9) == "IX"); 112 assert(toRoman(10) == "X"); 113 assert(toRoman(33) == "XXXIII"); 114 assert(toRoman(1111) == "MCXI"); 115 assert(toRoman(1999) == "MCMXCIX"); 116 assert(toRoman(550) == "DL"); 117 assert(toRoman(400) == "CD"); 118 assert(toRoman(40) == "XL"); 119 120 // invalid 121 assert(toRoman(0) == ""); 122 123 }