:- module roman2. :- interface. :- import_module io. :- pred main(io::di, io::uo) is det. :- implementation. :- import_module char, int, list, string. main(!IO) :- command_line_arguments(Args, !IO), filter_map(to_int, Args, CleanArgs), foldl((pred(Arg::in, !.IO::di, !:IO::uo) is det :- ( Roman = to_roman(Arg) -> format("%i => %s", [i(Arg), s(from_char_list(Roman))], !IO), nl(!IO) ; format("%i cannot be converted.", [i(Arg)], !IO), nl(!IO) ) ), CleanArgs, !IO). :- func to_roman(int) = list(char). :- mode to_roman(in) = out is semidet. to_roman(N) = ( N >= 1000 -> ['M'] ++ to_roman(N - 1000) ;( N >= 100 -> digit(N / 100, 'C', 'D', 'M') ++ to_roman(N rem 100) ;( N >= 10 -> digit(N / 10, 'X', 'L', 'C') ++ to_roman(N rem 10) ;( N >= 1 -> digit(N, 'I', 'V', 'X') ; [] ) ) ) ). :- func digit(int, char, char, char) = list(char). :- mode digit(in, in, in, in) = out is semidet. digit(1, X, _, _) = [X]. digit(2, X, _, _) = [X, X]. digit(3, X, _, _) = [X, X, X]. digit(4, X, Y, _) = [X, Y]. digit(5, _, Y, _) = [Y]. digit(6, X, Y, _) = [Y, X]. digit(7, X, Y, _) = [Y, X, X]. digit(8, X, Y, _) = [Y, X, X, X]. digit(9, X, _, Z) = [X, Z]. :- end_module roman2.