New improved int2roma() and roma2int() functions

Second approximation of the conversion between old roman and integer digits. Added some error checks and released the roma2int() functionality

%% convert between integer and old roman
%% usage:
%%   convert:int2roma(555) -> "DLV" 
%%   convert:int2roma(999) -> "DCCCCLXXXXVIIII" 
%%   convert:roma2int("DLV") -> 555
%%   convert:roma2int("DCCCCLXXXXVIIII") -> 999

-module(convert).
-export([int2roma/1,roma2int/1]).

i2r(1)    -> "I";
i2r(5)    -> "V";
i2r(10)   -> "X";
i2r(50)   -> "L";
i2r(100)  -> "C";
i2r(500)  -> "D";
i2r(1000) -> "M".

r2i($I) -> 1;
r2i($V) -> 5;
r2i($X) -> 10;
r2i($L) -> 50;
r2i($C) -> 100;
r2i($D) -> 500;
r2i($M) -> 1000;
r2i(X)  ->  erlang:error("invalid input: " ++ [X]).

roma2int(L) -> catch(lists:sum([r2i(X) || X <- L])).

int2roma(X) when is_integer(X), X < 10000 ->
  lists:flatten(int2roma(X,[1000,500,100,50,10,5,1])).
int2roma(_,[]) -> []; %% done
int2roma(X, [H|T])->
  [lists:duplicate(X div H, i2r(H))|int2roma(X rem H, T)].

Still a lot to do, like checking the order of character occurences in the string ( roma2int() ), better error messages etc. But for an exercise maybe it's enough.

  • 05-06-2007 update: based on yhara-san's code I simplified the roma2int() function to one line. It even reports which exactly is the bad symbol. if check in int2roma() replaced by clause with guard.
  • 07-06-2007 update: some hints from the okkez-san's code - no need to have a X>0 clause, cause in case of 0 it just will not execute the lists:duplicate part.
  • 07-06-2007 update: List1++List2 construction seems depricated (slow), replaced with [H|T] in int2roma().