tasks a-s
This commit is contained in:
parent
47bf37c096
commit
b83f433714
12433 changed files with 156208 additions and 123 deletions
3
Task/Roman-numerals-Decode/0DESCRIPTION
Normal file
3
Task/Roman-numerals-Decode/0DESCRIPTION
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
Create a function that takes a Roman numeral as its argument and returns its value as a numeric decimal integer. You don't need to validate the form of the Roman numeral.
|
||||
|
||||
Modern Roman numerals are written by expressing each decimal digit of the number to be encoded separately, starting with the leftmost digit and skipping any 0s. So 1990 is rendered "MCMXC" (1000 = M, 900 = CM, 90 = XC) and 2008 is rendered "MMVIII" (2000 = MM, 8 = VIII). The Roman numeral for 1666, "MDCLXVI", uses each letter in descending order.
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
PROC roman to int = (STRING roman) INT:
|
||||
BEGIN
|
||||
PROC roman digit value = (CHAR roman digit) INT:
|
||||
(roman digit = "M" | 1000 |:
|
||||
roman digit = "D" | 500 |:
|
||||
roman digit = "C" | 100 |:
|
||||
roman digit = "L" | 50 |:
|
||||
roman digit = "X" | 10 |:
|
||||
roman digit = "V" | 5 |:
|
||||
roman digit = "I" | 1);
|
||||
|
||||
INT result := 0, previous value := 0, run := 0;
|
||||
|
||||
FOR i FROM LWB roman TO UPB roman
|
||||
DO
|
||||
INT value = roman digit value(roman[i]);
|
||||
IF previous value = value THEN
|
||||
run +:= value
|
||||
ELSE
|
||||
IF previous value < value THEN
|
||||
result -:= run
|
||||
ELSE
|
||||
result +:= run
|
||||
FI;
|
||||
run := previous value := value
|
||||
FI
|
||||
OD;
|
||||
|
||||
result +:= run
|
||||
END;
|
||||
|
||||
MODE TEST = STRUCT (STRING input, INT expected output);
|
||||
|
||||
[] TEST roman test = (
|
||||
("MMXI", 2011), ("MIM", 1999),
|
||||
("MCMLVI", 1956), ("MDCLXVI", 1666),
|
||||
("XXCIII", 83), ("LXXIIX", 78),
|
||||
("IIIIX", 6)
|
||||
);
|
||||
|
||||
print(("Test input Value Got", newline, "--------------------------", newline));
|
||||
FOR i FROM LWB roman test TO UPB roman test
|
||||
DO
|
||||
INT output = roman to int(input OF roman test[i]);
|
||||
printf(($g, n (12 - UPB input OF roman test[i]) x$, input OF roman test[i]));
|
||||
printf(($g(5), 1x, g(5), 1x$, expected output OF roman test[i], output));
|
||||
printf(($b("ok", "not ok"), 1l$, output = expected output OF roman test[i]))
|
||||
OD
|
||||
39
Task/Roman-numerals-Decode/ANTLR/roman-numerals-decode.antlr
Normal file
39
Task/Roman-numerals-Decode/ANTLR/roman-numerals-decode.antlr
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
/* Parse Roman Numerals
|
||||
|
||||
Nigel Galloway March 16th., 2012
|
||||
*/
|
||||
grammar ParseRN ;
|
||||
|
||||
options {
|
||||
language = Java;
|
||||
}
|
||||
@members {
|
||||
int rnValue;
|
||||
int ONE;
|
||||
}
|
||||
|
||||
parseRN: ({rnValue = 0;} rn NEWLINE {System.out.println($rn.text + " = " + rnValue);})*
|
||||
;
|
||||
|
||||
rn : (Thousand {rnValue += 1000;})* hundreds? tens? units?;
|
||||
|
||||
hundreds: {ONE = 0;} (h9 | h5) {if (ONE > 3) System.out.println ("Too many hundreds");};
|
||||
h9 : Hundred {ONE += 1;} (FiveHund {rnValue += 400;}| Thousand {rnValue += 900;}|{rnValue += 100;} (Hundred {rnValue += 100; ONE += 1;})*);
|
||||
h5 : FiveHund {rnValue += 500;} (Hundred {rnValue += 100; ONE += 1;})*;
|
||||
|
||||
tens : {ONE = 0;} (t9 | t5) {if (ONE > 3) System.out.println ("Too many tens");};
|
||||
t9 : Ten {ONE += 1;} (Fifty {rnValue += 40;}| Hundred {rnValue += 90;}|{rnValue += 10;} (Ten {rnValue += 10; ONE += 1;})*);
|
||||
t5 : Fifty {rnValue += 50;} (Ten {rnValue += 10; ONE += 1;})*;
|
||||
|
||||
units : {ONE = 0;} (u9 | u5) {if (ONE > 3) System.out.println ("Too many ones");};
|
||||
u9 : One {ONE += 1;} (Five {rnValue += 4;}| Ten {rnValue += 9;}|{rnValue += 1;} (One {rnValue += 1; ONE += 1;})*);
|
||||
u5 : Five {rnValue += 5;} (One {rnValue += 1; ONE += 1;})*;
|
||||
|
||||
One : 'I';
|
||||
Five : 'V';
|
||||
Ten : 'X';
|
||||
Fifty : 'L';
|
||||
Hundred: 'C';
|
||||
FiveHund: 'D';
|
||||
Thousand: 'M' ;
|
||||
NEWLINE: '\r'? '\n' ;
|
||||
23
Task/Roman-numerals-Decode/AWK/roman-numerals-decode.awk
Normal file
23
Task/Roman-numerals-Decode/AWK/roman-numerals-decode.awk
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# syntax: GAWK -f ROMAN_NUMERALS_DECODE.AWK
|
||||
BEGIN {
|
||||
leng = split("MCMXC MMVIII MDCLXVI",arr," ")
|
||||
for (i=1; i<=leng; i++) {
|
||||
n = arr[i]
|
||||
printf("%s = %s\n",n,roman2arabic(n))
|
||||
}
|
||||
exit(0)
|
||||
}
|
||||
function roman2arabic(r, a,i,p,q,u,ua,una,unr) {
|
||||
r = toupper(r)
|
||||
unr = "MDCLXVI" # each Roman numeral in descending order
|
||||
una = "1000 500 100 50 10 5 1" # and its Arabic equivalent
|
||||
split(una,ua," ")
|
||||
i = split(r,u,"")
|
||||
a = ua[index(unr,u[i])]
|
||||
while (--i) {
|
||||
p = index(unr,u[i])
|
||||
q = index(unr,u[i+1])
|
||||
a += ua[p] * ((p>q) ? -1 : 1)
|
||||
}
|
||||
return( (a>0) ? a : "" )
|
||||
}
|
||||
46
Task/Roman-numerals-Decode/Ada/roman-numerals-decode.ada
Normal file
46
Task/Roman-numerals-Decode/Ada/roman-numerals-decode.ada
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
with Ada.Text_IO;
|
||||
|
||||
procedure Decode_Roman_Numerals is
|
||||
|
||||
function Roman_To_Integer(A_Roman: String) return Integer is
|
||||
|
||||
function Decode_Roman_Digit (A_Char: Character) return Integer is
|
||||
begin
|
||||
case A_Char is
|
||||
when 'M' | 'm' => return 1000;
|
||||
when 'D' | 'd' => return 500;
|
||||
when 'C' | 'c' => return 100;
|
||||
when 'L' | 'l' => return 50;
|
||||
when 'X' | 'x' => return 10;
|
||||
when 'V' | 'v' => return 5;
|
||||
when 'I' | 'i' => return 1;
|
||||
when others => return 0;
|
||||
end case;
|
||||
end Decode_Roman_Digit;
|
||||
|
||||
L_Curr_Val: Integer;
|
||||
L_Last_Val: Integer;
|
||||
|
||||
Result: Integer;
|
||||
begin
|
||||
Result := 0;
|
||||
|
||||
L_Last_Val := 0;
|
||||
|
||||
for i in reverse 1 .. A_Roman'Length loop
|
||||
L_Curr_Val := Decode_Roman_Digit(A_Roman(I));
|
||||
if L_Curr_Val < L_Last_Val then
|
||||
Result := Result - L_Curr_Val;
|
||||
else
|
||||
Result := Result + L_Curr_Val;
|
||||
end if;
|
||||
L_Last_Val := L_Curr_Val;
|
||||
end loop;
|
||||
return Result;
|
||||
end Roman_To_Integer;
|
||||
|
||||
begin
|
||||
Ada.Text_IO.Put_Line(Integer'Image(Roman_To_Integer("MCMXC"))); -- 1990
|
||||
Ada.Text_IO.Put_Line(Integer'Image(Roman_To_Integer("MMVIII"))); -- 2008
|
||||
Ada.Text_IO.Put_Line(Integer'Image(Roman_To_Integer("MDCLXVI"))); -- 1666
|
||||
end Decode_Roman_Numerals;
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
Roman_Decode(str){
|
||||
res := 0
|
||||
Loop Parse, str
|
||||
{
|
||||
n := {M: 1000, D:500, C:100, L:50, X:10, V:5, I:1}[A_LoopField]
|
||||
If ( n > OldN ) && OldN
|
||||
res -= 2*OldN
|
||||
res += n, oldN := n
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
test = MCMXC|MMVIII|MDCLXVI
|
||||
Loop Parse, test, |
|
||||
res .= A_LoopField "`t= " Roman_Decode(A_LoopField) "`r`n"
|
||||
clipboard := res
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
PRINT "MCMXCIX", FNromandecode("MCMXCIX")
|
||||
PRINT "MMXII", FNromandecode("MMXII")
|
||||
PRINT "MDCLXVI", FNromandecode("MDCLXVI")
|
||||
PRINT "MMMDCCCLXXXVIII", FNromandecode("MMMDCCCLXXXVIII")
|
||||
END
|
||||
|
||||
DEF FNromandecode(roman$)
|
||||
LOCAL i%, j%, p%, n%, r%()
|
||||
DIM r%(7) : r%() = 0,1,5,10,50,100,500,1000
|
||||
FOR i% = LEN(roman$) TO 1 STEP -1
|
||||
j% = INSTR("IVXLCDM", MID$(roman$,i%,1))
|
||||
IF j%=0 ERROR 100, "Invalid character"
|
||||
IF j%>=p% n% += r%(j%) ELSE n% -= r%(j%)
|
||||
p% = j%
|
||||
NEXT
|
||||
= n%
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
( unroman
|
||||
= nbr,lastVal,val
|
||||
. 0:?nbr:?lastVal
|
||||
& @( low$!arg
|
||||
: ?
|
||||
%@?L
|
||||
( ?
|
||||
& (m.1000)
|
||||
(d.500)
|
||||
(c.100)
|
||||
(l.50)
|
||||
(x.10)
|
||||
(v.5)
|
||||
(i.1)
|
||||
: ? (!L.?val) ?
|
||||
& (!val:~>!lastVal|!val+-2*!lastVal)
|
||||
+ !nbr
|
||||
: ?nbr
|
||||
& !val:?lastVal
|
||||
& ~
|
||||
)
|
||||
)
|
||||
| !nbr
|
||||
)
|
||||
& (M.1000)
|
||||
(MCXI.1111)
|
||||
(CMXI.911)
|
||||
(MCM.1900)
|
||||
(MCMXC.1990)
|
||||
(MMVIII.2008)
|
||||
(MMIX.2009)
|
||||
(MCDXLIV.1444)
|
||||
(MDCLXVI.1666)
|
||||
(MMXII.2012)
|
||||
: ?years
|
||||
& (test=.out$(!arg unroman$!arg))
|
||||
& ( !years
|
||||
: ? (?L.?D) (?&test$!L&~)
|
||||
| done
|
||||
);
|
||||
48
Task/Roman-numerals-Decode/C++/roman-numerals-decode.cpp
Normal file
48
Task/Roman-numerals-Decode/C++/roman-numerals-decode.cpp
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
static std::map<char , int> Romans;
|
||||
|
||||
int RomanToInt( const std::string &roman ) {
|
||||
int number = 0 ;
|
||||
// look for all the letters in the array
|
||||
for ( std::string::const_iterator i = roman.begin( ) ; i != roman.end( ) ; i++ ) {
|
||||
std::map<char , int>::const_iterator it1 = Romans.find( *i ) ;
|
||||
if ( it1 == Romans.end( ) ) {
|
||||
std::cerr << *i << " not a valid Roman numeral character." << std::endl ;
|
||||
return -1 ;
|
||||
}
|
||||
int pos1 = it1->second ;
|
||||
if ( i + 1 != roman.end( ) ) {
|
||||
std::map<char , int>::const_iterator it2 = Romans.find( *( i + 1 ) );
|
||||
if ( it2 == Romans.end( ) ) {
|
||||
std::cerr << *( i + 1 ) << " not a valid Roman numeral character." << std::endl ;
|
||||
return -1 ;
|
||||
}
|
||||
int pos2 = it2->second ;
|
||||
if ( pos2 > pos1 ) {
|
||||
number += pos2 - pos1 ;
|
||||
i++ ;
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
number += pos1 ;
|
||||
}
|
||||
return number ;
|
||||
}
|
||||
|
||||
int main( ) {
|
||||
Romans[ 'I' ] = 1 ;
|
||||
Romans[ 'V' ] = 5 ;
|
||||
Romans[ 'X' ] = 10 ;
|
||||
Romans[ 'L' ] = 50 ;
|
||||
Romans[ 'C' ] = 100 ;
|
||||
Romans[ 'D' ] = 500 ;
|
||||
Romans[ 'M' ] = 1000 ;
|
||||
|
||||
std::cout << "MCMXC in Roman numerals is " << RomanToInt( "MCMXC" ) << " in Arabic!\n" ;
|
||||
std::cout << "And MDCLXVI for the Romans is " << RomanToInt( "MDCLXVI" ) << " in better known Arabic figures!\n" ;
|
||||
return 0 ;
|
||||
}
|
||||
47
Task/Roman-numerals-Decode/C/roman-numerals-decode.c
Normal file
47
Task/Roman-numerals-Decode/C/roman-numerals-decode.c
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int digits[26] = { 0, 0, 100, 500, 0, 0, 0, 0, 1, 1, 0, 50, 1000, 0, 0, 0, 0, 0, 0, 0, 5, 5, 0, 10, 0, 0 };
|
||||
|
||||
/* assuming ASCII, do upper case and get index in alphabet. could also be
|
||||
inline int VALUE(char x) { return digits [ (~0x20 & x) - 'A' ]; }
|
||||
if you think macros are evil */
|
||||
#define VALUE(x) digits[(~0x20 & (x)) - 'A']
|
||||
|
||||
int decode(const char * roman)
|
||||
{
|
||||
const char *bigger;
|
||||
int current;
|
||||
int arabic = 0;
|
||||
while (*roman != '\0') {
|
||||
current = VALUE(*roman);
|
||||
/* if (!current) return -1;
|
||||
note: -1 can be used as error code; Romans didn't even have zero
|
||||
*/
|
||||
bigger = roman;
|
||||
|
||||
/* look for a larger digit, like IV or XM */
|
||||
while (VALUE(*bigger) <= current && *++bigger != '\0');
|
||||
|
||||
if (*bigger == '\0')
|
||||
arabic += current;
|
||||
else {
|
||||
arabic += VALUE(*bigger);
|
||||
while (roman < bigger)
|
||||
arabic -= VALUE(* (roman++) );
|
||||
}
|
||||
|
||||
roman ++;
|
||||
}
|
||||
return arabic;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const char * romans[] = { "MCmxC", "MMVIII", "MDClXVI", "MCXLUJ" };
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
printf("%s\t%d\n", romans[i], decode(romans[i]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
(defn ro2ar [r]
|
||||
(->> (reverse r)
|
||||
(replace (zipmap "MDCLXVI" [1000 500 100 50 10 5 1]))
|
||||
(partition-by identity)
|
||||
(map (partial apply +))
|
||||
(reduce #(if (< %1 %2) (+ %1 %2) (- %1 %2)))))
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
roman_to_demical = (s) ->
|
||||
# s is well-formed Roman Numeral >= I
|
||||
numbers =
|
||||
M: 1000
|
||||
D: 500
|
||||
C: 100
|
||||
L: 50
|
||||
X: 10
|
||||
V: 5
|
||||
I: 1
|
||||
|
||||
result = 0
|
||||
for c in s
|
||||
num = numbers[c]
|
||||
result += num
|
||||
if old_num < num
|
||||
# If old_num exists and is less than num, then
|
||||
# we need to subtract it twice, once because we
|
||||
# have already added it on the last pass, and twice
|
||||
# to conform to the Roman convention that XC = 90,
|
||||
# not 110.
|
||||
result -= 2 * old_num
|
||||
old_num = num
|
||||
result
|
||||
|
||||
tests =
|
||||
IV: 4
|
||||
XLII: 42
|
||||
MCMXC: 1990
|
||||
MMVIII: 2008
|
||||
MDCLXVI: 1666
|
||||
|
||||
for roman, expected of tests
|
||||
dec = roman_to_demical(roman)
|
||||
console.log "error" if dec != expected
|
||||
console.log "#{roman} = #{dec}"
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
(defun parse-roman (r)
|
||||
(loop for l on (map 'list (lambda (c)
|
||||
(getf '(#\I 1 #\V 5 #\X 10 #\L 50 #\C 100 #\D 500 #\M 1000) c))
|
||||
(string-upcase r))
|
||||
sum (let ((a (first l)) (b (second l)))
|
||||
(if (and b (< a b)) (- a) a))))
|
||||
;; test code
|
||||
(dolist (r '("MCMXC" "MDCLXVI" "MMVIII"))
|
||||
(format t "~a: ~d~%" r (parse-roman r)))
|
||||
19
Task/Roman-numerals-Decode/D/roman-numerals-decode-1.d
Normal file
19
Task/Roman-numerals-Decode/D/roman-numerals-decode-1.d
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
import std.regex, std.algorithm;
|
||||
|
||||
int toArabic(in string s) /*pure nothrow*/ {
|
||||
static immutable weights = [1000, 900, 500, 400, 100,
|
||||
90, 50, 40, 10, 9, 5, 4, 1];
|
||||
static immutable symbols = ["M","CM","D","CD","C","XC",
|
||||
"L","XL","X","IX","V","IV","I"];
|
||||
|
||||
int arabic;
|
||||
foreach (m; s.match(regex(r"CM|CD|XC|XL|IX|IV|[MDCLXVI]", "g")))
|
||||
arabic += weights[symbols.countUntil(m.hit)];
|
||||
return arabic;
|
||||
}
|
||||
|
||||
void main() {
|
||||
assert(toArabic("MCMXC") == 1990);
|
||||
assert(toArabic("MMVIII") == 2008);
|
||||
assert(toArabic("MDCLXVI") == 1666);
|
||||
}
|
||||
20
Task/Roman-numerals-Decode/D/roman-numerals-decode-2.d
Normal file
20
Task/Roman-numerals-Decode/D/roman-numerals-decode-2.d
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import std.regex, std.algorithm;
|
||||
|
||||
immutable int[string] w2s;
|
||||
|
||||
nothrow static this() {
|
||||
w2s = ["IX": 9, "C": 100, "D": 500, "CM": 900, "I": 1,
|
||||
"XC": 90, "M": 1000, "L": 50, "CD": 400, "XL": 40,
|
||||
"V": 5, "X": 10, "IV": 4];
|
||||
}
|
||||
|
||||
int toArabic(in string s) /*pure nothrow*/ {
|
||||
auto ms = match(s, regex("CM|CD|XC|XL|IX|IV|[MDCLXVI]", "g"));
|
||||
return reduce!((a, m) => a + w2s[m.hit])(0, ms);
|
||||
}
|
||||
|
||||
void main() {
|
||||
assert("MCMXC".toArabic == 1990);
|
||||
assert("MMVIII".toArabic == 2008);
|
||||
assert("MDCLXVI".toArabic == 1666);
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
program RomanNumeralsDecode;
|
||||
|
||||
{$APPTYPE CONSOLE}
|
||||
|
||||
function RomanToInteger(const aRoman: string): Integer;
|
||||
function DecodeRomanDigit(aChar: Char): Integer;
|
||||
begin
|
||||
case aChar of
|
||||
'M', 'm': Result := 1000;
|
||||
'D', 'd': Result := 500;
|
||||
'C', 'c': Result := 100;
|
||||
'L', 'l': Result := 50;
|
||||
'X', 'x': Result := 10;
|
||||
'V', 'v': Result := 5;
|
||||
'I', 'i': Result := 1
|
||||
else
|
||||
Result := 0;
|
||||
end;
|
||||
end;
|
||||
|
||||
var
|
||||
i: Integer;
|
||||
lCurrVal: Integer;
|
||||
lLastVal: Integer;
|
||||
begin
|
||||
Result := 0;
|
||||
|
||||
lLastVal := 0;
|
||||
for i := Length(aRoman) downto 1 do
|
||||
begin
|
||||
lCurrVal := DecodeRomanDigit(aRoman[i]);
|
||||
if lCurrVal < lLastVal then
|
||||
Result := Result - lCurrVal
|
||||
else
|
||||
Result := Result + lCurrVal;
|
||||
lLastVal := lCurrVal;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
Writeln(RomanToInteger('MCMXC')); // 1990
|
||||
Writeln(RomanToInteger('MMVIII')); // 2008
|
||||
Writeln(RomanToInteger('MDCLXVI')); // 1666
|
||||
end.
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
(defun ro2ar (RN)
|
||||
"translate a roman number RN into arabic number.
|
||||
Its argument RN is wether a symbol, wether a list.
|
||||
Returns the arabic number. (ro2ar 'C) gives 100,
|
||||
(ro2ar '(X X I V)) gives 24"
|
||||
(cond
|
||||
((eq RN 'M) 1000)
|
||||
((eq RN 'D) 500)
|
||||
((eq RN 'C) 100)
|
||||
((eq RN 'L) 50)
|
||||
((eq RN 'X) 10)
|
||||
((eq RN 'V) 5)
|
||||
((eq RN 'I) 1)
|
||||
((null (cdr RN)) (ro2ar (car RN))) ;; stop recursion
|
||||
((< (ro2ar (car RN)) (ro2ar (car (cdr RN)))) (- (ro2ar (cdr RN)) (ro2ar (car RN)))) ;; "IV" -> 5-1=4
|
||||
(t (+ (ro2ar (car RN)) (ro2ar (cdr RN)))))) ;; "VI" -> 5+1=6
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
constant symbols = "MDCLXVI", weights = {1000,500,100,50,10,5,1}
|
||||
function romanDec(sequence roman)
|
||||
integer n, lastval, arabic
|
||||
lastval = 0
|
||||
arabic = 0
|
||||
for i = length(roman) to 1 by -1 do
|
||||
n = find(roman[i],symbols)
|
||||
if n then
|
||||
n = weights[n]
|
||||
end if
|
||||
if n < lastval then
|
||||
arabic -= n
|
||||
else
|
||||
arabic += n
|
||||
end if
|
||||
lastval = n
|
||||
end for
|
||||
return arabic
|
||||
end function
|
||||
|
||||
? romanDec("MCMXCIX")
|
||||
? romanDec("MDCLXVI")
|
||||
? romanDec("XXV")
|
||||
? romanDec("CMLIV")
|
||||
? romanDec("MMXI")
|
||||
26
Task/Roman-numerals-Decode/Forth/roman-numerals-decode.fth
Normal file
26
Task/Roman-numerals-Decode/Forth/roman-numerals-decode.fth
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
create (arabic)
|
||||
1000 128 * char M + ,
|
||||
500 128 * char D + ,
|
||||
100 128 * char C + ,
|
||||
50 128 * char L + ,
|
||||
10 128 * char X + ,
|
||||
5 128 * char V + ,
|
||||
1 128 * char I + ,
|
||||
does>
|
||||
7 cells bounds do
|
||||
i @ over over 127 and = if nip 7 rshift leave else drop then
|
||||
1 cells +loop dup
|
||||
;
|
||||
|
||||
: >arabic
|
||||
0 dup >r >r
|
||||
begin
|
||||
over over
|
||||
while
|
||||
c@ dup (arabic) rot <>
|
||||
while
|
||||
r> over r> over over > if 2* negate + else drop then + swap >r >r 1 /string
|
||||
repeat then drop 2drop r> r> drop
|
||||
;
|
||||
|
||||
s" MCMLXXXIV" >arabic .
|
||||
41
Task/Roman-numerals-Decode/Fortran/roman-numerals-decode.f
Normal file
41
Task/Roman-numerals-Decode/Fortran/roman-numerals-decode.f
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
program Roman_decode
|
||||
implicit none
|
||||
|
||||
write(*,*) decode("MCMXC"), decode("MMVIII"), decode("MDCLXVI")
|
||||
|
||||
contains
|
||||
|
||||
function decode(roman) result(arabic)
|
||||
character(*), intent(in) :: roman
|
||||
integer :: i, n, lastval, arabic
|
||||
|
||||
arabic = 0
|
||||
lastval = 0
|
||||
do i = len(roman), 1, -1
|
||||
select case(roman(i:i))
|
||||
case ('M','m')
|
||||
n = 1000
|
||||
case ('D','d')
|
||||
n = 500
|
||||
case ('C','c')
|
||||
n = 100
|
||||
case ('L','l')
|
||||
n = 50
|
||||
case ('X','x')
|
||||
n = 10
|
||||
case ('V','v')
|
||||
n = 5
|
||||
case ('I','i')
|
||||
n = 1
|
||||
case default
|
||||
n = 0
|
||||
end select
|
||||
if (n < lastval) then
|
||||
arabic = arabic - n
|
||||
else
|
||||
arabic = arabic + n
|
||||
end if
|
||||
lastval = n
|
||||
end do
|
||||
end function decode
|
||||
end program Roman_decode
|
||||
84
Task/Roman-numerals-Decode/Go/roman-numerals-decode-1.go
Normal file
84
Task/Roman-numerals-Decode/Go/roman-numerals-decode-1.go
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var m = map[rune]int{
|
||||
'I': 1,
|
||||
'V': 5,
|
||||
'X': 10,
|
||||
'L': 50,
|
||||
'C': 100,
|
||||
'D': 500,
|
||||
'M': 1000,
|
||||
}
|
||||
|
||||
func parseRoman(s string) (r int, err error) {
|
||||
if s == "" {
|
||||
return 0, errors.New("Empty string")
|
||||
}
|
||||
is := []rune(s) // easier to convert string up front
|
||||
var c0 rune // c0: roman character last read
|
||||
var cv0 int // cv0: value of cv
|
||||
|
||||
// the key to the algorithm is to process digits from right to left
|
||||
for i := len(is) - 1; i >= 0; i-- {
|
||||
// read roman digit
|
||||
c := is[i]
|
||||
k := c == 0x305 // unicode overbar combining character
|
||||
if k {
|
||||
if i == 0 {
|
||||
return 0, errors.New(
|
||||
"Overbar combining character invalid at position 0")
|
||||
}
|
||||
i--
|
||||
c = is[i]
|
||||
}
|
||||
cv := m[c]
|
||||
if cv == 0 {
|
||||
if c == 0x0305 {
|
||||
return 0, errors.New(fmt.Sprintf(
|
||||
"Overbar combining character invalid at position %d", i))
|
||||
} else {
|
||||
return 0, errors.New(fmt.Sprintf(
|
||||
"Character unrecognized as Roman digit: %c", c))
|
||||
}
|
||||
}
|
||||
if k {
|
||||
c = -c // convention indicating overbar
|
||||
cv *= 1000
|
||||
}
|
||||
|
||||
// handle cases of new, same, subtractive, changed, in that order.
|
||||
switch {
|
||||
default: // case 4: digit change
|
||||
fallthrough
|
||||
case c0 == 0: // case 1: no previous digit
|
||||
c0 = c
|
||||
cv0 = cv
|
||||
case c == c0: // case 2: same digit
|
||||
case cv*5 == cv0 || cv*10 == cv0: // case 3: subtractive
|
||||
// handle next digit as new.
|
||||
// a subtractive digit doesn't count as a previous digit.
|
||||
c0 = 0
|
||||
r -= cv // subtract...
|
||||
continue // ...instead of adding
|
||||
}
|
||||
r += cv // add, in all cases except subtractive
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
// parse three numbers mentioned in task description
|
||||
for _, r := range []string{"MCMXC", "MMVIII", "MDCLXVI"} {
|
||||
v, err := parseRoman(r)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
} else {
|
||||
fmt.Println(r, "==", v)
|
||||
}
|
||||
}
|
||||
}
|
||||
38
Task/Roman-numerals-Decode/Go/roman-numerals-decode-2.go
Normal file
38
Task/Roman-numerals-Decode/Go/roman-numerals-decode-2.go
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var m = map[string]int{
|
||||
"I": 1,
|
||||
"V": 5,
|
||||
"X": 10,
|
||||
"L": 50,
|
||||
"C": 100,
|
||||
"D": 500,
|
||||
"M": 1000,
|
||||
}
|
||||
|
||||
// function, per task description
|
||||
func from_roman(roman string) (arabic int) {
|
||||
last_digit := 1000
|
||||
for _, r := range strings.Split(roman, "") {
|
||||
digit := m[r]
|
||||
if last_digit < digit {
|
||||
arabic -= 2 * last_digit
|
||||
}
|
||||
last_digit = digit
|
||||
arabic += digit
|
||||
}
|
||||
|
||||
return arabic
|
||||
}
|
||||
|
||||
func main() {
|
||||
// parse three numbers mentioned in task description
|
||||
for _, roman_digit := range []string{"MCMXC", "MMVIII", "MDCLXVI"} {
|
||||
fmt.Printf("%-10s == %d\n", roman_digit, from_roman(roman_digit))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
enum RomanDigits {
|
||||
I(1), V(5), X(10), L(50), C(100), D(500), M(1000);
|
||||
|
||||
private magnitude;
|
||||
private RomanDigits(magnitude) { this.magnitude = magnitude }
|
||||
|
||||
String toString() { super.toString() + "=${magnitude}" }
|
||||
|
||||
static BigInteger parse(String numeral) {
|
||||
assert numeral != null && !numeral.empty
|
||||
def digits = (numeral as List).collect {
|
||||
RomanDigits.valueOf(it)
|
||||
}
|
||||
def L = digits.size()
|
||||
(0..<L).inject(0g) { total, i ->
|
||||
def sign = (i == L - 1 || digits[i] >= digits[i+1]) ? 1 : -1
|
||||
total + sign * digits[i].magnitude
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
println """
|
||||
Digit Values = ${RomanDigits.values()}
|
||||
M => ${RomanDigits.parse('M')}
|
||||
MCXI => ${RomanDigits.parse('MCXI')}
|
||||
CMXI => ${RomanDigits.parse('CMXI')}
|
||||
MCM => ${RomanDigits.parse('MCM')}
|
||||
MCMXC => ${RomanDigits.parse('MCMXC')}
|
||||
MMVIII => ${RomanDigits.parse('MMVIII')}
|
||||
MMIX => ${RomanDigits.parse('MMIX')}
|
||||
MCDXLIV => ${RomanDigits.parse('MCDXLIV')}
|
||||
MDCLXVI => ${RomanDigits.parse('MDCLXVI')}
|
||||
"""
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import Data.List (isPrefixOf)
|
||||
|
||||
mapping = [("M",1000),("CM",900),("D",500),("CD",400),("C",100),("XC",90),
|
||||
("L",50),("XL",40),("X",10),("IX",9),("V",5),("IV",4),("I",1)]
|
||||
|
||||
toArabic :: String -> Int
|
||||
toArabic "" = 0
|
||||
toArabic str = num + toArabic xs
|
||||
where (num, xs):_ = [ (num, drop (length n) str) | (n,num) <- mapping, isPrefixOf n str ]
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
link numbers
|
||||
|
||||
procedure main()
|
||||
every R := "MCMXC"|"MDCLXVI"|"MMVIII" do
|
||||
write(R, " = ",unroman(R))
|
||||
end
|
||||
20
Task/Roman-numerals-Decode/Icon/roman-numerals-decode-2.icon
Normal file
20
Task/Roman-numerals-Decode/Icon/roman-numerals-decode-2.icon
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
procedure unroman(s) #: convert Roman numeral to integer
|
||||
local nbr,lastVal,val
|
||||
|
||||
nbr := lastVal := 0
|
||||
s ? {
|
||||
while val := case map(move(1)) of {
|
||||
"m": 1000
|
||||
"d": 500
|
||||
"c": 100
|
||||
"l": 50
|
||||
"x": 10
|
||||
"v": 5
|
||||
"i": 1
|
||||
} do {
|
||||
nbr +:= if val <= lastVal then val else val - 2 * lastVal
|
||||
lastVal := val
|
||||
}
|
||||
}
|
||||
return nbr
|
||||
end
|
||||
1
Task/Roman-numerals-Decode/J/roman-numerals-decode-1.j
Normal file
1
Task/Roman-numerals-Decode/J/roman-numerals-decode-1.j
Normal file
|
|
@ -0,0 +1 @@
|
|||
rom2d=: [: (+/ .* _1^ 0,~ 2</\ ]) 1 5 10 50 100 500 1000 {~ 'IVXLCDM'&i.
|
||||
6
Task/Roman-numerals-Decode/J/roman-numerals-decode-2.j
Normal file
6
Task/Roman-numerals-Decode/J/roman-numerals-decode-2.j
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
rom2d 'MCMXC'
|
||||
1990
|
||||
rom2d 'MDCLXVI'
|
||||
1666
|
||||
rom2d 'MMVIII'
|
||||
2008
|
||||
37
Task/Roman-numerals-Decode/Java/roman-numerals-decode.java
Normal file
37
Task/Roman-numerals-Decode/Java/roman-numerals-decode.java
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
public class Roman {
|
||||
private static int decodeSingle(char letter) {
|
||||
switch(letter) {
|
||||
case 'M': return 1000;
|
||||
case 'D': return 500;
|
||||
case 'C': return 100;
|
||||
case 'L': return 50;
|
||||
case 'X': return 10;
|
||||
case 'V': return 5;
|
||||
case 'I': return 1;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
public static int decode(String roman) {
|
||||
int result = 0;
|
||||
String uRoman = roman.toUpperCase(); //case-insensitive
|
||||
for(int i = 0;i < uRoman.length() - 1;i++) {//loop over all but the last character
|
||||
//if this character has a lower value than the next character
|
||||
if (decodeSingle(uRoman.charAt(i)) < decodeSingle(uRoman.charAt(i+1))) {
|
||||
//subtract it
|
||||
result -= decodeSingle(uRoman.charAt(i));
|
||||
} else {
|
||||
//add it
|
||||
result += decodeSingle(uRoman.charAt(i));
|
||||
}
|
||||
}
|
||||
//decode the last character, which is always added
|
||||
result += decodeSingle(uRoman.charAt(uRoman.length()-1));
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println(decode("MCMXC")); //1990
|
||||
System.out.println(decode("MMVIII")); //2008
|
||||
System.out.println(decode("MDCLXVI")); //1666
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
var Roman = {
|
||||
Values: [['M', 1000], ['CM', 900], ['D', 500], ['CD', 400],
|
||||
['C', 100], ['XC', 90], ['L', 50], ['XL', 40],
|
||||
['X', 10], ['IX', 9], ['V', 5], ['IV', 4],
|
||||
['I', 1]],
|
||||
|
||||
parse: function(str) {
|
||||
var result = 0
|
||||
for (var i=0; i<Roman.Values.length; ++i) {
|
||||
var pair = Roman.Values[i]
|
||||
var key = pair[0]
|
||||
var value = pair[1]
|
||||
var regex = RegExp('^' + key)
|
||||
while (str.match(regex)) {
|
||||
result += value
|
||||
str = str.replace(regex, '')
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
var test_data = ['MCMXC', 'MDCLXVI', 'MMVIII']
|
||||
for (var i=0; i<test_data.length; ++i) {
|
||||
var test_datum = test_data[i]
|
||||
print(test_datum + ": " + Roman.parse(test_datum))
|
||||
}
|
||||
1
Task/Roman-numerals-Decode/K/roman-numerals-decode-1.k
Normal file
1
Task/Roman-numerals-Decode/K/roman-numerals-decode-1.k
Normal file
|
|
@ -0,0 +1 @@
|
|||
romd: {v:1 5 10 50 100 500 1000@"IVXLCDM"?/:x; +/v*_-1^(>':v),0}
|
||||
2
Task/Roman-numerals-Decode/K/roman-numerals-decode-2.k
Normal file
2
Task/Roman-numerals-Decode/K/roman-numerals-decode-2.k
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
romd'("MCMXC";"MMVIII";"MDCLXVI")
|
||||
1990 2008 1666
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
print "MCMXCIX = "; romanDec( "MCMXCIX") '1999
|
||||
print "MDCLXVI = "; romanDec( "MDCLXVI") '1666
|
||||
print "XXV = "; romanDec( "XXV") '25
|
||||
print "CMLIV = "; romanDec( "CMLIV") '954
|
||||
print "MMXI = "; romanDec( "MMXI") '2011
|
||||
|
||||
end
|
||||
|
||||
function romanDec( roman$)
|
||||
arabic =0
|
||||
lastval =0
|
||||
|
||||
for i = len( roman$) to 1 step -1
|
||||
select case upper$( mid$( roman$, i, 1))
|
||||
case "M"
|
||||
n = 1000
|
||||
case "D"
|
||||
n = 500
|
||||
case "C"
|
||||
n = 100
|
||||
case "L"
|
||||
n = 50
|
||||
case "X"
|
||||
n = 10
|
||||
case "V"
|
||||
n = 5
|
||||
case "I"
|
||||
n = 1
|
||||
case else
|
||||
n = 0
|
||||
end select
|
||||
|
||||
if n <lastval then
|
||||
arabic =arabic -n
|
||||
else
|
||||
arabic =arabic +n
|
||||
end if
|
||||
|
||||
lastval =n
|
||||
next
|
||||
|
||||
romanDec =arabic
|
||||
end function
|
||||
35
Task/Roman-numerals-Decode/Logo/roman-numerals-decode.logo
Normal file
35
Task/Roman-numerals-Decode/Logo/roman-numerals-decode.logo
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
; Roman numeral decoder
|
||||
|
||||
; First, some useful substring utilities
|
||||
to starts_with? :string :prefix
|
||||
if empty? :prefix [output "true]
|
||||
if empty? :string [output "false]
|
||||
if not equal? first :string first :prefix [output "false]
|
||||
output starts_with? butfirst :string butfirst :prefix
|
||||
end
|
||||
|
||||
to remove_prefix :string :prefix
|
||||
if or empty? :prefix not starts_with? :string :prefix [output :string]
|
||||
output remove_prefix butfirst :string butfirst :prefix
|
||||
end
|
||||
|
||||
; Our list of Roman numeral values
|
||||
make "values [[M 1000] [CM 900] [D 500] [CD 400] [C 100] [XC 90] [L 50]
|
||||
[XL 40] [X 10] [IX 9] [V 5] [IV 4] [I 1]]
|
||||
|
||||
; Function to do the work
|
||||
to from_roman :str
|
||||
local "n make "n 0
|
||||
foreach :values [
|
||||
local "s make "s first ?
|
||||
local "v make "v last ?
|
||||
while [starts_with? :str :s] [
|
||||
make "n sum n :v
|
||||
make "str remove_prefix :str :s
|
||||
]
|
||||
]
|
||||
output :n
|
||||
end
|
||||
|
||||
foreach [MCMXC MDCLXVI MMVIII] [print (sentence (word ? "|: |) from_roman ?)]
|
||||
bye
|
||||
25
Task/Roman-numerals-Decode/Lua/roman-numerals-decode.lua
Normal file
25
Task/Roman-numerals-Decode/Lua/roman-numerals-decode.lua
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
function ToNumeral( roman )
|
||||
local Num = { ["M"] = 1000, ["D"] = 500, ["C"] = 100, ["L"] = 50, ["X"] = 10, ["V"] = 5, ["I"] = 1 }
|
||||
local numeral = 0
|
||||
|
||||
local i = 1
|
||||
local strlen = string.len(roman)
|
||||
while i < strlen do
|
||||
local z1, z2 = Num[ string.sub(roman,i,i) ], Num[ string.sub(roman,i+1,i+1) ]
|
||||
if z1 < z2 then
|
||||
numeral = numeral + ( z2 - z1 )
|
||||
i = i + 2
|
||||
else
|
||||
numeral = numeral + z1
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
if i <= strlen then numeral = numeral + Num[ string.sub(roman,i,i) ] end
|
||||
|
||||
return numeral
|
||||
end
|
||||
|
||||
print( ToNumeral( "MCMXC" ) )
|
||||
print( ToNumeral( "MMVIII" ) )
|
||||
print( ToNumeral( "MDCLXVI" ) )
|
||||
|
|
@ -0,0 +1 @@
|
|||
FromDigits["MMCDV", "Roman"]
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/* NetRexx */
|
||||
options replace format comments java crossref savelog symbols binary
|
||||
|
||||
/* 1990 2008 1666 */
|
||||
years = Rexx('MCMXC MMVIII MDCLXVI')
|
||||
|
||||
loop y_ = 1 to years.words
|
||||
Say years.word(y_).right(10) || ':' decode(years.word(y_))
|
||||
end y_
|
||||
|
||||
return
|
||||
|
||||
method decode(arg) public static returns int signals IllegalArgumentException
|
||||
|
||||
parse arg.upper roman .
|
||||
if roman.verify('MDCLXVI') \= 0 then signal IllegalArgumentException
|
||||
|
||||
-- always insert the value of the least significant numeral
|
||||
decnum = rchar(roman.substr(roman.length, 1))
|
||||
loop d_ = 1 to roman.length - 1
|
||||
if rchar(roman.substr(d_, 1)) < rchar(roman.substr(d_ + 1, 1)) then do
|
||||
-- Handle cases where numerals are not in descending order
|
||||
-- subtract the value of the numeral
|
||||
decnum = decnum - rchar(roman.substr(d_, 1))
|
||||
end
|
||||
else do
|
||||
-- Normal case
|
||||
-- add the value of the numeral
|
||||
decnum = decnum + rchar(roman.substr(d_, 1))
|
||||
end
|
||||
end d_
|
||||
|
||||
return decnum
|
||||
|
||||
method rchar(arg) public static returns int
|
||||
|
||||
parse arg.upper ch +1 .
|
||||
select case ch
|
||||
when 'M' then digit = 1000
|
||||
when 'D' then digit = 500
|
||||
when 'C' then digit = 100
|
||||
when 'L' then digit = 50
|
||||
when 'X' then digit = 10
|
||||
when 'V' then digit = 5
|
||||
when 'I' then digit = 1
|
||||
otherwise digit = 0
|
||||
end
|
||||
|
||||
return digit
|
||||
27
Task/Roman-numerals-Decode/OCaml/roman-numerals-decode.ocaml
Normal file
27
Task/Roman-numerals-Decode/OCaml/roman-numerals-decode.ocaml
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
let decimal_of_roman roman =
|
||||
let arabic = ref 0 in
|
||||
let lastval = ref 0 in
|
||||
for i = (String.length roman) - 1 downto 0 do
|
||||
let n =
|
||||
match roman.[i] with
|
||||
| 'M' | 'm' -> 1000
|
||||
| 'D' | 'd' -> 500
|
||||
| 'C' | 'c' -> 100
|
||||
| 'L' | 'l' -> 50
|
||||
| 'X' | 'x' -> 10
|
||||
| 'V' | 'v' -> 5
|
||||
| 'I' | 'i' -> 1
|
||||
| _ -> 0
|
||||
in
|
||||
if n < !lastval
|
||||
then arabic := !arabic - n
|
||||
else arabic := !arabic + n;
|
||||
lastval := n
|
||||
done;
|
||||
!arabic
|
||||
|
||||
let () =
|
||||
Printf.printf " %d\n" (decimal_of_roman "MCMXC");
|
||||
Printf.printf " %d\n" (decimal_of_roman "MMVIII");
|
||||
Printf.printf " %d\n" (decimal_of_roman "MDCLXVI");
|
||||
;;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
fromRoman(s)={
|
||||
my(v=Vecsmall(s),key=vector(88),cur,t=0,tmp);
|
||||
key[73]=1;key[86]=5;key[88]=10;key[76]=50;key[67]=100;key[68]=500;key[77]=1000;
|
||||
cur=key[v[1]];
|
||||
for(i=2,#v,
|
||||
tmp=key[v[i]];
|
||||
if(!cur, cur=tmp; next);
|
||||
if(tmp>cur,
|
||||
t+=tmp-cur;
|
||||
cur=0
|
||||
,
|
||||
t+=cur;
|
||||
cur=tmp
|
||||
)
|
||||
);
|
||||
t+cur
|
||||
};
|
||||
86
Task/Roman-numerals-Decode/PHP/roman-numerals-decode.php
Normal file
86
Task/Roman-numerals-Decode/PHP/roman-numerals-decode.php
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Elad Yosifon <elad.yosifon@gmail.com>
|
||||
*/
|
||||
$roman_to_decimal = array(
|
||||
'I' => 1,
|
||||
'V' => 5,
|
||||
'X' => 10,
|
||||
'L' => 50,
|
||||
'C' => 100,
|
||||
'D' => 500,
|
||||
'M' => 1000,
|
||||
);
|
||||
|
||||
/**
|
||||
* @param $number
|
||||
* @return int
|
||||
*/
|
||||
function roman2decimal($number)
|
||||
{
|
||||
global $roman_to_decimal;
|
||||
|
||||
// breaks the string into an array of chars
|
||||
$digits = str_split($number);
|
||||
$lastIndex = count($digits)-1;
|
||||
$sum = 0;
|
||||
|
||||
foreach($digits as $index => $digit)
|
||||
{
|
||||
if(!isset($digits[$index]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(isset($roman_to_decimal[$digit]))
|
||||
{
|
||||
if($index < $lastIndex)
|
||||
{
|
||||
$left = $roman_to_decimal[$digits[$index]];
|
||||
$right = $roman_to_decimal[$digits[$index+1]];
|
||||
if($left < $right)
|
||||
{
|
||||
$sum += ($right - $left);
|
||||
unset($digits[$index+1],$left, $right);
|
||||
continue;
|
||||
}
|
||||
unset($left, $right);
|
||||
}
|
||||
}
|
||||
$sum += $roman_to_decimal[$digit];
|
||||
}
|
||||
|
||||
return $sum;
|
||||
}
|
||||
|
||||
/*============= OUTPUT =============*/
|
||||
header('Content-Type: text/plain');
|
||||
|
||||
$tests = array(
|
||||
"I" => array(roman2decimal('I'), 1),
|
||||
"II" => array(roman2decimal('II'), 2),
|
||||
"III" => array(roman2decimal('III'), 3),
|
||||
"IV" => array(roman2decimal('IV'), 4),
|
||||
"V" => array(roman2decimal('V'), 5),
|
||||
"VI" => array(roman2decimal('VI'), 6),
|
||||
"VII" => array(roman2decimal('VII'), 7),
|
||||
"IX" => array(roman2decimal('IX'), 9),
|
||||
"X" => array(roman2decimal('X'), 10),
|
||||
"XI" => array(roman2decimal('XI'), 11),
|
||||
"XIV" => array(roman2decimal('XIV'), 14),
|
||||
"XV" => array(roman2decimal('XV'), 15),
|
||||
"XVI" => array(roman2decimal('XVI'), 16),
|
||||
"XVIV" => array(roman2decimal('XVIV'), 19),
|
||||
"XIX" => array(roman2decimal('XIX'), 19),
|
||||
"MDCLXVI" => array(roman2decimal('MDCLXVI'), 1666),
|
||||
"MCMXC" => array(roman2decimal('MCMXC'), 1990),
|
||||
"MMVIII" => array(roman2decimal('MMVIII'), 2008),
|
||||
"MMMCLIX" => array(roman2decimal('MMMCLIX'), 3159),
|
||||
"MCMLXXVII" => array(roman2decimal('MCMLXXVII'), 1977),
|
||||
);
|
||||
|
||||
|
||||
foreach($tests as $key => $value)
|
||||
{
|
||||
echo "($key == {$value[0]}) => " . ($value[0] === $value[1] ? "true" : "false, should be {$value[1]}.") . "\n";
|
||||
}
|
||||
46
Task/Roman-numerals-Decode/PL-I/roman-numerals-decode.pli
Normal file
46
Task/Roman-numerals-Decode/PL-I/roman-numerals-decode.pli
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
test_decode: procedure options (main); /* 28 January 2013 */
|
||||
declare roman character (20) varying;
|
||||
|
||||
do roman = 'i', 'ii', 'iii', 'iv', 'v', 'vi', 'vii', 'viii', 'iix',
|
||||
'ix', 'x', 'xi', 'xiv', 'MCMLXIV', 'MCMXC', 'MDCLXVI',
|
||||
'MIM', 'MM', 'MMXIII';
|
||||
put skip list (roman, decode(roman));
|
||||
end;
|
||||
|
||||
decode: procedure (roman) returns (fixed(15));
|
||||
declare roman character (*) varying;
|
||||
declare (current, previous) character (1);
|
||||
declare n fixed (15);
|
||||
declare i fixed binary;
|
||||
|
||||
previous = ''; n = 0;
|
||||
do i = length(roman) to 1 by -1;
|
||||
current = substr(roman, i, 1);
|
||||
if digit_value(current) < digit_value(previous) then
|
||||
n = n - digit_value(current);
|
||||
else if digit_value(current) > digit_value(previous) then
|
||||
do;
|
||||
n = n + digit_value(current);
|
||||
previous = current;
|
||||
end;
|
||||
else
|
||||
n = n + digit_value(current);
|
||||
end;
|
||||
return (n);
|
||||
end decode;
|
||||
|
||||
digit_value: procedure (roman_char) returns (fixed);
|
||||
declare roman_char character(1);
|
||||
select (roman_char);
|
||||
when ('M', 'm') return (1000);
|
||||
when ('D', 'd') return (500);
|
||||
when ('C', 'c') return (100);
|
||||
when ('L', 'l') return (50);
|
||||
when ('X', 'x') return (10);
|
||||
when ('V', 'v') return (5);
|
||||
when ('I', 'i') return (1);
|
||||
otherwise return (0);
|
||||
end;
|
||||
end digit_value;
|
||||
|
||||
end test_decode;
|
||||
83
Task/Roman-numerals-Decode/PL-SQL/roman-numerals-decode.sql
Normal file
83
Task/Roman-numerals-Decode/PL-SQL/roman-numerals-decode.sql
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*****************************************************************
|
||||
* $Author: Atanas Kebedjiev $
|
||||
*****************************************************************
|
||||
* PL/SQL code can be run as anonymous block.
|
||||
* To test, execute the whole script or create the functions and then e.g. 'select rdecode('2012') from dual;
|
||||
* Please note that task definition does not describe fully some current rules, such as
|
||||
* * subtraction - IX XC CM are the valid subtraction combinations
|
||||
* * A subtraction character cannot be repeated: 8 is expressed as VIII and not as IIX
|
||||
* * V L and D cannot be used for subtraction
|
||||
* * Any numeral cannot be repeated more than 3 times: 1910 should be MCMX and not MDCCCCX
|
||||
* Code below does not validate the Roman numeral itself and will return a result even for a non-compliant number
|
||||
* E.g. both MCMXCIX and IMM will return 1999 but the first one is the correct notation
|
||||
*/
|
||||
|
||||
DECLARE
|
||||
|
||||
FUNCTION rvalue(c IN CHAR) RETURN NUMBER IS
|
||||
i INTEGER;
|
||||
BEGIN
|
||||
i := 0;
|
||||
CASE (c)
|
||||
when 'M' THEN i := 1000;
|
||||
when 'D' THEN i := 500;
|
||||
when 'C' THEN i := 100;
|
||||
when 'L' THEN i := 50;
|
||||
when 'X' THEN i := 10;
|
||||
when 'V' THEN i := 5;
|
||||
when 'I' THEN i := 1;
|
||||
END CASE;
|
||||
RETURN i;
|
||||
END;
|
||||
|
||||
|
||||
FUNCTION decode(rn IN VARCHAR2) RETURN NUMBER IS
|
||||
i INTEGER;
|
||||
l INTEGER;
|
||||
cr CHAR; -- current Roman numeral as substring from r
|
||||
cv INTEGER; -- value of current Roman numeral
|
||||
|
||||
gr CHAR; -- next Roman numeral
|
||||
gv NUMBER; -- value of the next numeral;
|
||||
|
||||
dv NUMBER; -- decimal value to return
|
||||
BEGIN
|
||||
l := length(rn);
|
||||
i := 1;
|
||||
dv := 0;
|
||||
while (i <= l)
|
||||
LOOP
|
||||
cr := substr(rn,i,1);
|
||||
cv := rvalue(cr);
|
||||
|
||||
/* Look for a larger numeral in next position, like IV or CM
|
||||
The number to subtract should be at least 1/10th of the bigger number
|
||||
CM and XC are valid, but IC and XM are not */
|
||||
IF (i < l) THEN
|
||||
gr := substr(rn,i+1,1);
|
||||
gv := rvalue(gr);
|
||||
IF (cv < gv ) THEN
|
||||
dv := dv - cv;
|
||||
ELSE
|
||||
dv := dv + cv;
|
||||
END IF;
|
||||
ELSE
|
||||
dv := dv + cv;
|
||||
END IF; -- need to add the last value unconditionally
|
||||
|
||||
i := i + 1;
|
||||
END LOOP;
|
||||
|
||||
RETURN dv;
|
||||
|
||||
END;
|
||||
|
||||
BEGIN
|
||||
|
||||
DBMS_OUTPUT.PUT_LINE ('MMXII = ' || rdecode('MMXII')); -- 2012
|
||||
DBMS_OUTPUT.PUT_LINE ('MCMLI = ' || rdecode('MCMLI')); -- 1951
|
||||
DBMS_OUTPUT.PUT_LINE ('MCMLXXXVII = ' || rdecode('MCMLXXXVII')); -- 1987
|
||||
DBMS_OUTPUT.PUT_LINE ('MDCLXVI = ' || rdecode('MDCLXVI')); -- 1666
|
||||
DBMS_OUTPUT.PUT_LINE ('MCMXCIX = ' || rdecode('MCMXCIX')); -- 1999
|
||||
|
||||
END;
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
sub rom-to-num($r) {
|
||||
[+] gather $r.uc ~~ /
|
||||
^
|
||||
[
|
||||
| M { take 1000 }
|
||||
| CM { take 900 }
|
||||
| D { take 500 }
|
||||
| CD { take 400 }
|
||||
| C { take 100 }
|
||||
| XC { take 90 }
|
||||
| L { take 50 }
|
||||
| XL { take 40 }
|
||||
| X { take 10 }
|
||||
| IX { take 9 }
|
||||
| V { take 5 }
|
||||
| IV { take 4 }
|
||||
| I { take 1 }
|
||||
]+
|
||||
$
|
||||
/;
|
||||
}
|
||||
|
||||
say "$_ => &rom-to-num($_)" for <MCMXC MDCLXVI MMVIII>;
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
sub rom-to-num($r) {
|
||||
[+] gather $r.uc ~~ /
|
||||
^
|
||||
( (C*)M { take 1000 - 100 * $0.chars } )*
|
||||
( (C*)D { take 500 - 100 * $0.chars } )?
|
||||
( (X*)C { take 100 - 10 * $0.chars } )*
|
||||
( (X*)L { take 50 - 10 * $0.chars } )?
|
||||
( (I*)X { take 10 - $0.chars } )*
|
||||
( (I*)V { take 5 - $0.chars } )?
|
||||
( I { take 1 } )*
|
||||
[ $ || { return NaN } ]
|
||||
/;
|
||||
}
|
||||
|
||||
say "$_ => ", rom-to-num($_) for <MCMXC mdclxvi MMViii IIXX ILL>;
|
||||
25
Task/Roman-numerals-Decode/Perl/roman-numerals-decode.pl
Normal file
25
Task/Roman-numerals-Decode/Perl/roman-numerals-decode.pl
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
use 5.10.0;
|
||||
|
||||
{
|
||||
my @trans = (
|
||||
[M => 1000], [CM => 900],
|
||||
[D => 500], [CD => 400],
|
||||
[C => 100], [XC => 90],
|
||||
[L => 50], [XL => 40],
|
||||
[X => 10], [IX => 9],
|
||||
[V => 5], [IV => 4],
|
||||
[I => 1],
|
||||
);
|
||||
|
||||
sub from_roman {
|
||||
my $r = shift;
|
||||
my $n = 0;
|
||||
foreach my $pair (@trans) {
|
||||
my ($k, $v) = @$pair;
|
||||
$n += $v while $r =~ s/^$k//i;
|
||||
}
|
||||
return $n
|
||||
}
|
||||
}
|
||||
|
||||
say "$_: ", from_roman($_) for qw(MCMXC MDCLXVI MMVIII);
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
(de roman2decimal (Rom)
|
||||
(let L (replace (chop Rom) 'M 1000 'D 500 'C 100 'L 50 'X 10 'V 5 'I 1)
|
||||
(sum '((A B) (if (>= A B) A (- A))) L (cdr L)) ) )
|
||||
32
Task/Roman-numerals-Decode/Prolog/roman-numerals-decode.pro
Normal file
32
Task/Roman-numerals-Decode/Prolog/roman-numerals-decode.pro
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
decode_digit(i, 1).
|
||||
decode_digit(v, 5).
|
||||
decode_digit(x, 10).
|
||||
decode_digit(l, 50).
|
||||
decode_digit(c, 100).
|
||||
decode_digit(d, 500).
|
||||
decode_digit(m, 1000).
|
||||
|
||||
decode_string(Sum, _, [], Sum).
|
||||
|
||||
decode_string(LastSum, LastValue, [Digit|Rest], NextSum) :-
|
||||
decode_digit(Digit, Value),
|
||||
Value < LastValue,
|
||||
Sum is LastSum - Value,
|
||||
decode_string(Sum, Value, Rest, NextSum).
|
||||
|
||||
decode_string(LastSum, LastValue, [Digit|Rest], NextSum) :-
|
||||
decode_digit(Digit, Value),
|
||||
Value >= LastValue,
|
||||
Sum is LastSum + Value,
|
||||
decode_string(Sum, Value, Rest, NextSum).
|
||||
|
||||
decode_string(Atom, Value) :-
|
||||
atom_chars(Atom, String),
|
||||
reverse(String, [Last|Rest]),
|
||||
decode_digit(Last, Start),
|
||||
decode_string(Start, Start, Rest, Value).
|
||||
|
||||
test :-
|
||||
decode_string(mcmxc, 1990),
|
||||
decode_string(mmviii, 2008),
|
||||
decode_string(mdclxvi, 1666).
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
Procedure romanDec(roman.s)
|
||||
Protected i, n, lastval, arabic
|
||||
|
||||
For i = Len(roman) To 1 Step -1
|
||||
Select UCase(Mid(roman, i, 1))
|
||||
Case "M"
|
||||
n = 1000
|
||||
Case "D"
|
||||
n = 500
|
||||
Case "C"
|
||||
n = 100
|
||||
Case "L"
|
||||
n = 50
|
||||
Case "X"
|
||||
n = 10
|
||||
Case "V"
|
||||
n = 5
|
||||
Case "I"
|
||||
n = 1
|
||||
Default
|
||||
n = 0
|
||||
EndSelect
|
||||
If (n < lastval)
|
||||
arabic - n
|
||||
Else
|
||||
arabic + n
|
||||
EndIf
|
||||
lastval = n
|
||||
Next
|
||||
|
||||
ProcedureReturn arabic
|
||||
EndProcedure
|
||||
|
||||
If OpenConsole()
|
||||
PrintN(Str(romanDec("MCMXCIX"))) ;1999
|
||||
PrintN(Str(romanDec("MDCLXVI"))) ;1666
|
||||
PrintN(Str(romanDec("XXV"))) ;25
|
||||
PrintN(Str(romanDec("CMLIV"))) ;954
|
||||
PrintN(Str(romanDec("MMXI"))) ;2011
|
||||
|
||||
Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input()
|
||||
CloseConsole()
|
||||
EndIf
|
||||
12
Task/Roman-numerals-Decode/Python/roman-numerals-decode-1.py
Normal file
12
Task/Roman-numerals-Decode/Python/roman-numerals-decode-1.py
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
_rdecode = dict(zip('MDCLXVI', (1000, 500, 100, 50, 10, 5, 1)))
|
||||
|
||||
def decode( roman ):
|
||||
result = 0
|
||||
for r, r1 in zip(roman, roman[1:]):
|
||||
rd, rd1 = _rdecode[r], _rdecode[r1]
|
||||
result += -rd if rd < rd1 else rd
|
||||
return result + _rdecode[roman[-1]]
|
||||
|
||||
if __name__ == '__main__':
|
||||
for r in 'MCMXC MMVIII MDCLXVI'.split():
|
||||
print( r, decode(r) )
|
||||
20
Task/Roman-numerals-Decode/Python/roman-numerals-decode-2.py
Normal file
20
Task/Roman-numerals-Decode/Python/roman-numerals-decode-2.py
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
roman_values = (('I',1), ('IV',4), ('V',5), ('IX',9),('X',10),('XL',40),('L',50),('XC',90),('C',100),
|
||||
('CD', 400), ('D', 500), ('CM', 900), ('M',1000))
|
||||
|
||||
def roman_value(roman):
|
||||
total=0
|
||||
for symbol,value in reversed(roman_values):
|
||||
while roman.startswith(symbol):
|
||||
total += value
|
||||
roman = roman[len(symbol):]
|
||||
return total
|
||||
|
||||
if __name__=='__main__':
|
||||
for value in "MCMXC", "MMVIII", "MDCLXVI":
|
||||
print('%s = %i' % (value, roman_value(value)))
|
||||
|
||||
""" Output:
|
||||
MCMXC = 1990
|
||||
MMVIII = 2008
|
||||
MDCLXVI = 1666
|
||||
"""
|
||||
63
Task/Roman-numerals-Decode/REXX/roman-numerals-decode-1.rexx
Normal file
63
Task/Roman-numerals-Decode/REXX/roman-numerals-decode-1.rexx
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/* Rexx */
|
||||
|
||||
Do
|
||||
/* 1990 2008 1666 */
|
||||
years = 'MCMXC MMVIII MDCLXVI'
|
||||
|
||||
Do y_ = 1 to words(years)
|
||||
Say right(word(years, y_), 10) || ':' decode(word(years, y_))
|
||||
End y_
|
||||
|
||||
Return
|
||||
End
|
||||
Exit
|
||||
|
||||
decode:
|
||||
Procedure
|
||||
Do
|
||||
Parse upper arg roman .
|
||||
|
||||
If verify(roman, 'MDCLXVI') = 0 then Do
|
||||
|
||||
/* always insert the value of the least significant numeral */
|
||||
decnum = rchar(substr(roman, length(roman), 1))
|
||||
Do d_ = 1 to length(roman) - 1
|
||||
If rchar(substr(roman, d_, 1)) < rchar(substr(roman, d_ + 1, 1)) then Do
|
||||
/* Handle cases where numerals are not in descending order */
|
||||
/* subtract the value of the numeral */
|
||||
decnum = decnum - rchar(substr(roman, d_, 1))
|
||||
End
|
||||
else Do
|
||||
/* Normal case */
|
||||
/* add the value of the numeral */
|
||||
decnum = decnum + rchar(substr(roman, d_, 1))
|
||||
End
|
||||
End d_
|
||||
End
|
||||
else Do
|
||||
decnum = roman 'contains invalid roman numerals'
|
||||
End
|
||||
|
||||
Return decnum
|
||||
End
|
||||
Exit
|
||||
|
||||
rchar:
|
||||
Procedure
|
||||
Do
|
||||
Parse upper arg ch +1 .
|
||||
|
||||
select
|
||||
when ch = 'M' then digit = 1000
|
||||
when ch = 'D' then digit = 500
|
||||
when ch = 'C' then digit = 100
|
||||
when ch = 'L' then digit = 50
|
||||
when ch = 'X' then digit = 10
|
||||
when ch = 'V' then digit = 5
|
||||
when ch = 'I' then digit = 1
|
||||
otherwise digit = 0
|
||||
end
|
||||
|
||||
Return digit
|
||||
End
|
||||
Exit
|
||||
30
Task/Roman-numerals-Decode/REXX/roman-numerals-decode-2.rexx
Normal file
30
Task/Roman-numerals-Decode/REXX/roman-numerals-decode-2.rexx
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*REXX program to convert Roman numeral number(s) to Arabic number(s). */
|
||||
|
||||
rYear='MCMXC' ; say right(rYear,9)':' rom2dec(rYear)
|
||||
rYear='mmviii' ; say right(rYear,9)':' rom2dec(rYear)
|
||||
rYear='MDCLXVI' ; say right(rYear,9)':' rom2dec(rYear)
|
||||
exit
|
||||
|
||||
rom2dec: procedure; arg roman .
|
||||
if verify(roman,'MDCLXVI')\==0 then do
|
||||
say 'invalid Roman number:' roman
|
||||
return '***error!***'
|
||||
end
|
||||
#=rChar(right(roman,1)) /*start with the last numeral*/
|
||||
do j=1 for length(roman)-1
|
||||
x=rChar(substr(roman,j ,1)) /*the current Roman numeral. */
|
||||
y=rChar(substr(roman,j+1,1)) /*the next Roman numeral. */
|
||||
if x<y then x=-x /*if x<y, then subtract, ¬add*/
|
||||
#=#+x
|
||||
end
|
||||
return #
|
||||
|
||||
rChar: procedure; arg _ /*convert a Roman number to an Arabic dig*/
|
||||
if _=='M' then return 1000
|
||||
if _=='D' then return 500
|
||||
if _=='C' then return 100
|
||||
if _=='L' then return 50
|
||||
if _=='X' then return 10
|
||||
if _=='V' then return 5
|
||||
if _=='I' then return 1
|
||||
return 0
|
||||
22
Task/Roman-numerals-Decode/REXX/roman-numerals-decode-3.rexx
Normal file
22
Task/Roman-numerals-Decode/REXX/roman-numerals-decode-3.rexx
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/*REXX program to convert Roman numerals ──► Arabic numerals (numbers).*/
|
||||
numeric digits 1000 /*we can handle big nums.*/
|
||||
y = 'MCMXC' ; say right(y,9)':' rom2dec(y)
|
||||
y = 'mmviii' ; say right(y,9)':' rom2dec(y)
|
||||
y = 'MDCLXVI' ; say right(y,9)':' rom2dec(y)
|
||||
y = 'MDQLXVI' ; say right(y,9)':' rom2dec(y)
|
||||
exit /*stick a fork in it, we're done.*/
|
||||
/*──────────────────────────────────ROM2DEC subroutine──────────────────*/
|
||||
rom2dec: procedure; h='0'x; #=0; $=1; arg n . /*uppercase N.*/
|
||||
n=translate(n,'()()',"[]{}"); _ = verify(n,'MDCLXVUIJ()')
|
||||
if _\==0 then return '***error!*** invalid Roman numeral:' substr(n,_,1)
|
||||
@.=1; @.m=1000; @.d=500; @.c=100; @.l=50; @.x=10; @.u=5; @.v=5
|
||||
|
||||
do k=length(n) to 1 by -1; _=substr(n,k,1) /*examine a Roman numeral*/
|
||||
/*(next) scale up or down*/
|
||||
if _=='(' | _==')' then do; $=$*1000; if _=='(' then $=1; iterate; end
|
||||
_=@._*$ /*scale it if necessary. */
|
||||
if _>h then h=_ /*remember Roman numeral.*/
|
||||
if _<h then #=#-_ /*char>next? Then sub. */
|
||||
else #=#+_ /* else add. */
|
||||
end /*k*/
|
||||
return # /*return Arabic number. */
|
||||
28
Task/Roman-numerals-Decode/Ruby/roman-numerals-decode.rb
Normal file
28
Task/Roman-numerals-Decode/Ruby/roman-numerals-decode.rb
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
def fromRoman(roman)
|
||||
r = roman.dup.upcase
|
||||
n = 0
|
||||
until r.empty? do
|
||||
case
|
||||
when r.start_with?('M') then v = 1000; len = 1
|
||||
when r.start_with?('CM') then v = 900; len = 2
|
||||
when r.start_with?('D') then v = 500; len = 1
|
||||
when r.start_with?('CD') then v = 400; len = 2
|
||||
when r.start_with?('C') then v = 100; len = 1
|
||||
when r.start_with?('XC') then v = 90; len = 2
|
||||
when r.start_with?('L') then v = 50; len = 1
|
||||
when r.start_with?('XL') then v = 40; len = 2
|
||||
when r.start_with?('X') then v = 10; len = 1
|
||||
when r.start_with?('IX') then v = 9; len = 2
|
||||
when r.start_with?('V') then v = 5; len = 1
|
||||
when r.start_with?('IV') then v = 4; len = 2
|
||||
when r.start_with?('I') then v = 1; len = 1
|
||||
else
|
||||
raise ArgumentError.new("invalid roman numerals: " + roman)
|
||||
end
|
||||
n += v
|
||||
r[0 .. len-1] = ""
|
||||
end
|
||||
n
|
||||
end
|
||||
|
||||
[ "MCMXC", "MMVIII", "MDCLXVI" ].each {|r| pp [r, fromRoman(r)]}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
print "MCMXCIX = "; romToDec( "MCMXCIX") '1999
|
||||
print "MDCLXVI = "; romToDec( "MDCLXVI") '1666
|
||||
print "XXV = "; romToDec( "XXV") '25
|
||||
print "CMLIV = "; romToDec( "CMLIV") '954
|
||||
print "MMXI = "; romToDec( "MMXI") '2011
|
||||
|
||||
function romToDec(roman$)
|
||||
for i = len(roman$) to 1 step -1
|
||||
x$ = mid$(roman$, i, 1)
|
||||
n = 0
|
||||
if x$ = "M" then n = 1000
|
||||
if x$ = "D" then n = 500
|
||||
if x$ = "C" then n = 100
|
||||
if x$ = "L" then n = 50
|
||||
if x$ = "X" then n = 10
|
||||
if x$ = "V" then n = 5
|
||||
if x$ = "I" then n = 1
|
||||
|
||||
if n < preNum then num = num - n else num = num + n
|
||||
preNum = n
|
||||
next
|
||||
|
||||
romToDec =num
|
||||
end function
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
* Roman to Arabic
|
||||
define('arabic(n)s,ch,val,sum,x') :(arabic_end)
|
||||
arabic s = 'M1000 D500 C100 L50 X10 V5 I1 '
|
||||
n = reverse(n)
|
||||
arab1 n len(1) . ch = :f(arab2)
|
||||
s ch break(' ') . val
|
||||
val = lt(val,x) (-1 * val)
|
||||
sum = sum + val; x = val :(arab1)
|
||||
arab2 arabic = sum :(return)
|
||||
arabic_end
|
||||
|
||||
* Test and display
|
||||
tstr = 'MMX MCMXCIX MCDXCII MLXVI CDLXXVI "
|
||||
tloop tstr break(' ') . r span(' ') = :f(out)
|
||||
astr = astr r '=' arabic(r) ' ' :(tloop)
|
||||
out output = astr
|
||||
end
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
* Roman to Arabic
|
||||
define("arabic1(romans,arabic1)rdigit,adigit,b4")
|
||||
romans1 = " 0 IX9 IV4 III3 II2 I1 VIII8 VII7 VI6 V5" :(arabic1_end)
|
||||
arabic1 ident(romans) :s(return)
|
||||
romans (break("IV") | rem) . b4 rem . rdigit = b4
|
||||
romans1 " " rdigit any("0123456789") . adigit
|
||||
arabic1 = adigit arabic1
|
||||
romans = replace(romans,"MDCLX","CLXVI") :(arabic1)
|
||||
arabic1_end
|
||||
* Test and display
|
||||
tstr = "MMX MCMXCIX MCDXCII MLXVI CDLXXVI "
|
||||
tloop tstr break(' ') . r span(' ') = :f(out)
|
||||
astr = astr r '=' arabic1(r) ' ' :(tloop)
|
||||
out output = astr
|
||||
end
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
* Roman to Arabic
|
||||
define("arabic1(romans,arabic1)rdigit,adigit,b4")
|
||||
romans1 = " 0 IX9 IV4 III3 II2 I1 VIII8 VII7 VI6 V5" :(arabic1_end)
|
||||
arabic1 ident(romans) :s(return)
|
||||
romans (break("IV") | rem) . b4 rem . rdigit = replace(b4,"MDCLX","CLXVI")
|
||||
romans1 " " rdigit any("0123456789") . adigit
|
||||
arabic1 = adigit arabic1 :(arabic1)
|
||||
arabic1_end
|
||||
* Test and display
|
||||
tstr = " MMX MCMXCIX MCDXCII MLXVI CDLXXVI "
|
||||
tstr span(' ') break(' ') $ r *?(astr = astr r '=' arabic1(r) ' ') fail
|
||||
output = astr
|
||||
end
|
||||
18
Task/Roman-numerals-Decode/Scala/roman-numerals-decode.scala
Normal file
18
Task/Roman-numerals-Decode/Scala/roman-numerals-decode.scala
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
def fromRoman( r:String ) : Int = {
|
||||
val arabicNumerals = List("CM"->900,"M"->1000,"CD"->400,"D"->500,"XC"->90,"C"->100,
|
||||
"XL"->40,"L"->50,"IX"->9,"X"->10,"IV"->4,"V"->5,"I"->1)
|
||||
|
||||
var s = r
|
||||
arabicNumerals.foldLeft(0){ (n,t) => {
|
||||
val l = s.length; s = s.replaceAll(t._1,""); val c = (l - s.length)/t._1.length // Get the frequency
|
||||
n + (c*t._2) // Add the arabic numerals up
|
||||
} }
|
||||
}
|
||||
|
||||
|
||||
// A small test
|
||||
def test( roman:String ) = println( roman + " => " + fromRoman( roman ) )
|
||||
|
||||
test("MCMXC")
|
||||
test("MMVIII")
|
||||
test("MDCLXVI")
|
||||
36
Task/Roman-numerals-Decode/Seed7/roman-numerals-decode.seed7
Normal file
36
Task/Roman-numerals-Decode/Seed7/roman-numerals-decode.seed7
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
$ include "seed7_05.s7i";
|
||||
|
||||
const func integer: ROMAN parse (in string: roman) is func
|
||||
result
|
||||
var integer: arabic is 0;
|
||||
local
|
||||
var integer: index is 0;
|
||||
var integer: number is 0;
|
||||
var integer: lastval is 0;
|
||||
begin
|
||||
for index range length(roman) downto 1 do
|
||||
case roman[index] of
|
||||
when {'M', 'm'}: number := 1000;
|
||||
when {'D', 'd'}: number := 500;
|
||||
when {'C', 'c'}: number := 100;
|
||||
when {'L', 'l'}: number := 50;
|
||||
when {'X', 'x'}: number := 10;
|
||||
when {'V', 'v'}: number := 5;
|
||||
when {'I', 'i'}: number := 1;
|
||||
otherwise: raise RANGE_ERROR;
|
||||
end case;
|
||||
if number < lastval then
|
||||
arabic -:= number;
|
||||
else
|
||||
arabic +:= number;
|
||||
end if;
|
||||
lastval := number;
|
||||
end for;
|
||||
end func;
|
||||
|
||||
const proc: main is func
|
||||
begin
|
||||
writeln(ROMAN parse "MCMXC");
|
||||
writeln(ROMAN parse "MMVIII");
|
||||
writeln(ROMAN parse "MDCLXVI");
|
||||
end func;
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
PROGRAM:ROM2DEC
|
||||
:Input Str1
|
||||
:Disp real(21,Str1)
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
PROGRAM:ROM2DEC
|
||||
:Input "ROMAN:",Str1
|
||||
:{1000,500,100,50,10,5,1}➞L1
|
||||
:0➞P
|
||||
:0➞Y
|
||||
:For(I,length(Str1),1,-1)
|
||||
:inString("MDCLXVI",sub(Str1,I,1))➞X
|
||||
:If X≤0:Then
|
||||
:Disp "BAD NUMBER"
|
||||
:Stop
|
||||
:End
|
||||
:L1(x)➞N
|
||||
:If N<P:Then
|
||||
:Y–N➞Y
|
||||
:Else
|
||||
:Y+N➞Y
|
||||
:End
|
||||
:N➞P
|
||||
:End
|
||||
:Disp Y
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
$$ MODE TUSCRIPT
|
||||
LOOP roman_number="MCMXC'MMVIII'MDCLXVI"
|
||||
arab_number=DECODE (roman_number,ROMAN)
|
||||
PRINT "Roman number ",roman_number," equals ", arab_number
|
||||
ENDLOOP
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
proc fromRoman rnum {
|
||||
set map {M 1000+ CM 900+ D 500+ CD 400+ C 100+ XC 90+ L 50+ XL 40+ X 10+ IX 9+ V 5+ IV 4+ I 1+}
|
||||
expr [string map $map $rnum]0}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
foreach r {MCMXC MDCLXVI MMVIII} {
|
||||
puts "$r\t-> [fromRoman $r]"
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// Main program for testing the function
|
||||
//
|
||||
do {
|
||||
Get_Input(10, "Enter a roman numeral: ", NOCR+STATLINE)
|
||||
Call("Roman_to_Arabic")
|
||||
Reg_Type(10) Message(" = ") Num_Type(#1)
|
||||
} while(#1)
|
||||
Return
|
||||
|
||||
// Convert Roman numeral into numeric value
|
||||
// in: @10 = Roman numeral
|
||||
// out: #1 = numeric value
|
||||
//
|
||||
:Roman_to_Arabic:
|
||||
Buf_Switch(Buf_Free)
|
||||
Ins_Text("M1000 D500 C100 L50 X10 V5 I1") Ins_Newline
|
||||
Reg_Ins(10) Ins_Char(' ')
|
||||
#1 = #2 = 0
|
||||
|
||||
Repeat(ALL) {
|
||||
#3 = #2 // #3 = previous character
|
||||
Goto_Line(2) // roman numeral to be converted
|
||||
if (At_EOL) {
|
||||
Break // all done
|
||||
}
|
||||
Reg_Copy_Block(11, CP, CP+1, DELETE) // next character in roman numeral
|
||||
if (Search(@11, BEGIN+ADVANCE+NOERR)) { // find character from the table
|
||||
#2 = Num_Eval(SUPPRESS) // corresponding numeric value
|
||||
if (#2 > #3) { // larger than previous digit?
|
||||
#1 -= #3 // substract previous digit
|
||||
} else {
|
||||
#1 += #3 // add previous digit
|
||||
}
|
||||
}
|
||||
}
|
||||
Reg_Empty(11)
|
||||
Buf_Quit(OK)
|
||||
Return
|
||||
27
Task/Roman-numerals-Decode/XPL0/roman-numerals-decode.xpl0
Normal file
27
Task/Roman-numerals-Decode/XPL0/roman-numerals-decode.xpl0
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
string 0; \use zero-terminated strings
|
||||
code CrLf=9, IntOut=11;
|
||||
|
||||
func Roman(Str); \Convert Roman numeral string to decimal value
|
||||
char Str;
|
||||
int I, Val, Val0, Sum;
|
||||
[I:= 0; Sum:= 0; Val0:= 5000;
|
||||
loop [case Str(I) of
|
||||
^M: Val:= 1000;
|
||||
^D: Val:= 500;
|
||||
^C: Val:= 100;
|
||||
^L: Val:= 50;
|
||||
^X: Val:= 10;
|
||||
^V: Val:= 5;
|
||||
^I: Val:= 1
|
||||
other return Sum; \zero string terminator
|
||||
I:= I+1;
|
||||
Sum:= Sum + Val;
|
||||
if Val > Val0 then Sum:= Sum - 2*Val0;
|
||||
Val0:= Val;
|
||||
];
|
||||
];
|
||||
|
||||
[IntOut(0, Roman("MCMXC")); CrLf(0);
|
||||
IntOut(0, Roman("MMVIII")); CrLf(0);
|
||||
IntOut(0, Roman("MDCLXVI")); CrLf(0);
|
||||
]
|
||||
Loading…
Add table
Add a link
Reference in a new issue