49 lines
1.4 KiB
Plaintext
49 lines
1.4 KiB
Plaintext
:- 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.
|