Task

Create a function taking a positive integer as its parameter and returning a string containing the Roman numeral representation of that integer. Modern Roman numerals are written by expressing each digit separately, starting with the left most digit and skipping any digit with a value of zero.



In Roman numerals:

 1990 is rendered: 1000=M, 900=CM, 90=XC; resulting in MCMXC
 2008 is written as 2000=MM, 8=VIII; or MMVIII
 1666 uses each Roman symbol in descending order: MDCLXVI


RomanEncode(UNSIGNED Int) := 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;
  dsWeights  := DATASET(13,TRANSFORM(ProcessRec,SELF.val := Int, SELF := []));
 
  SymbolStr(i,n,STRING s) := CHOOSE(n+1,'',SetSymbols[i],SetSymbols[i]+SetSymbols[i],SetSymbols[i]+SetSymbols[i]+SetSymbols[i],s);
 
  RECORDOF(dsWeights) XF(dsWeights L, dsWeights R, INTEGER C) := TRANSFORM
    ThisVal := IF(C=1,R.Val,L.Val);
    IsDone := ThisVal = 0;
    SELF.Roman := IF(IsDone,L.Roman,L.Roman + SymbolStr(C,ThisVal DIV SetWeights[C],L.Roman));
    SELF.val := IF(IsDone,0,ThisVal - ((ThisVal DIV SetWeights[C])*SetWeights[C]));
  END;
  i := ITERATE(dsWeights,XF(LEFT,RIGHT,COUNTER));
  RETURN i[13].Roman;
END;
 
RomanEncode(1954);  //MCMLIV 
RomanEncode(1990 ); //MCMXC  
RomanEncode(2008 ); //MMVIII 
RomanEncode(1666);  //MDCLXVI