41 lines
1.5 KiB
Prolog
41 lines
1.5 KiB
Prolog
IMPORT STD;
|
|
RomanDecode(STRING s) := FUNCTION
|
|
SetWeights := [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
|
|
SetSymbols := ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
|
|
ProcessRec := RECORD
|
|
UNSIGNED val;
|
|
STRING Roman;
|
|
END;
|
|
dsSymbols := DATASET(13,TRANSFORM(ProcessRec,SELF.Roman := s, SELF := []));
|
|
|
|
RECORDOF(dsSymbols) XF(dsSymbols L, dsSymbols R, INTEGER C) := TRANSFORM
|
|
ThisRoman := IF(C=1,R.Roman,L.Roman);
|
|
IsDone := ThisRoman = '';
|
|
Repeatable := C IN [1,5,9,13];
|
|
SymSize := IF(C % 2 = 0, 2, 1);
|
|
IsNext := STD.Str.StartsWith(ThisRoman,SetSymbols[C]);
|
|
SymLen := IF(IsNext,
|
|
IF(NOT Repeatable,
|
|
SymSize,
|
|
MAP(NOT IsDone AND ThisRoman[1] = ThisRoman[2] AND ThisRoman[1] = ThisRoman[3] => 3,
|
|
NOT IsDone AND ThisRoman[1] = ThisRoman[2] => 2,
|
|
NOT IsDone => 1,
|
|
0)),
|
|
0);
|
|
|
|
SymbolWeight(STRING s) := IF(NOT Repeatable,
|
|
SetWeights[C],
|
|
CHOOSE(LENGTH(s),SetWeights[C],SetWeights[C]*2,SetWeights[C]*3,0));
|
|
|
|
SELF.Roman := IF(IsDone,ThisRoman,ThisRoman[SymLen+1..]);
|
|
SELF.val := IF(IsDone,L.val,L.Val + IF(IsNext,SymbolWeight(ThisRoman[1..SymLen]),0));
|
|
END;
|
|
i := ITERATE(dsSymbols,XF(LEFT,RIGHT,COUNTER));
|
|
RETURN i[13].val;
|
|
END;
|
|
|
|
RomanDecode('MCMLIV'); //1954
|
|
RomanDecode('MCMXC'); //1990
|
|
RomanDecode('MMVIII'); //2008
|
|
RomanDecode('MDCLXVI'); //1666
|
|
RomanDecode('MDLXVI'); //1566
|