prolog convert numbers into roman numerals

杀马特。学长 韩版系。学妹 提交于 2019-11-29 14:00:19
false

Try to formulate the problem differently: Write a grammar () to relate an integer and a list of characters denoting roman numerals. Here is a start:

:- use_module(library(clpfd)).

roman(0) --> "".
roman(N0) --> "I", { 1 #=< N0, N0 #=< 3, N1 #= N0-1}, roman(N1).

You can use it like so:

?- phrase(roman(3), L).
L = "III" ;
false.

or

?- phrase(roman(N), "II").
N = 2 ;
false.

or, if you don't know what to ask, simply ask the most general question:

?- phrase(roman(N), L).
N = 0,
L = [] ;
N = 1,
L = "I" ;
N = 2,
L = "II" ;
N = 3,
L = "III" ;
false.

To get answers compactly like L = "III", use :- set_prolog_flag(double_quotes,chars). See this answer for more.

You should change your toroman/1 procedure to something like toroman/2 that returns the roman numeral instead of just printing it.

Then you would be able to easily compare a roman numeral with the result from calling toroman/2 to the integer.

Note also that your current procedure will loop until getting a stack overflow if you backtrack for another solution. You should either guard each clause that recursively calls itself to recurse only if the parameter of the call is non-negative or add as the first clause a check that fails safely, e.g.:

roman(N):- N < 0, !, fail.

After changing toroman/1 to return the roman literal you would get something like this (just modified a bit your code to return the literal as the second argument):

toroman(N, _):- N < 0, !, fail.
toroman(0, []).
toroman(N, ['I'|Roman]) :- N < 4, M is N - 1, toroman(M, Roman).
toroman(4, ['IV']).
toroman(5, ['V']).
toroman(N, ['V'|Roman]) :- N < 9, M is N - 5, toroman(M, Roman).
toroman(9, ['IX']).
toroman(N, ['X'|Roman]) :- N < 40, M is N - 10, toroman(M, Roman).
toroman(N, ['XL'|Roman]) :- N < 50, M is N - 40, toroman(M, Roman).
toroman(N, ['L'|Roman]) :- N < 90, M is N - 50, toroman(M, Roman).
toroman(N, ['XC'|Roman]) :- N < 100, M is N - 90, toroman(M, Roman).
toroman(N, ['C'|Roman]) :- N < 400, M is N - 100, toroman(M, Roman).
toroman(N, ['CD'|Roman]) :- N < 500, M is N - 400, toroman(M, Roman).
toroman(N, ['DD'|Roman]) :- N < 900, M is N - 500, toroman(M, Roman).
toroman(N, ['CM'|Roman]) :- N < 1000, M is N - 900, toroman(M, Roman).
toroman(N, ['M'|Roman]) :- N < 4000, M is N - 1000, toroman(M, Roman).

roman(N, R) :- toroman(N, L), atomic_list_concat(L, R).

roman(N) :- roman(N, R), write(R).

Then you could simply call roman(N, R) and test whether R unifies with your roman numeral of interest.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!