prolog将数字转换为罗马数字

Muh*_*sag 6 numbers prolog roman-numerals dcg clpfd

我有这个代码将整数转换为罗马数字我需要添加一个函数,将整数与罗马数字输入进行比较,并显示它是否为try或false,例如:roman(v,5).真正

toroman(0).
toroman(N) :- N < 4, put("I"), M is N - 1, toroman(M).
toroman(N) :- N = 4, put("I"), put("V").
toroman(N) :- N = 5, put("V").
toroman(N) :- N < 9, put("V"), M is N - 5, toroman(M).
toroman(N) :- N = 9, put("I"), put("X").
toroman(N) :- N < 40, put("X"), M is N - 10, toroman(M).
toroman(N) :- N < 50, put("X"), put("L"), M is N - 40, toroman(M).
toroman(N) :- N < 90, put("L"), M is N - 50, toroman(M).
toroman(N) :- N < 100, put("X"), put("C"), M is N - 90, toroman(M).
toroman(N) :- N < 400, put("C"), M is N - 100, toroman(M).
toroman(N) :- N < 500, put("C"), put("D"), M is N - 400, toroman(M).
toroman(N) :- N < 900, put("D"), put("D"), M is N - 500, toroman(M).
toroman(N) :- N < 1000, put("C"), put("M"), M is N - 900, toroman(M).
toroman(N) :- N < 4000, put("M"), M is N - 1000, toroman(M).



roman(N) :- toroman(N).
Run Code Online (Sandbox Code Playgroud)

fal*_*lse 5

尝试以不同的方式表达问题:写一个语法()来关联一个整数和一个表示罗马数字的字符列表.这是一个开始:

:- use_module(library(clpfd)).

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

您可以像这样使用它:

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

要么

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

或者,如果您不知道该问什么,只需询问最一般的问题:

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

要获得紧凑的答案L = "III",:- set_prolog_flag(double_quotes,chars).请参阅此答案以获取更多信息.

  • 使用CLP(FD)在DCG上表达语义似乎真的很有趣! (4认同)
  • @chac:SWI中的CLP(FD)实际上是整数算术的更纯粹的替代品. (3认同)
  • 它提供了如此高水平的结构,它不仅仅是算术,至少是实际的. (3认同)
  • 是的,在Prolog中使用CLP(FD)非常棒.谢谢马库斯!! (3认同)
  • @chac:大多数CLP(FD)实现具有严重的正确性和其他限制,这使得它们无法用作替代品. (2认同)

gus*_*bro 0

您应该将toroman/1程序更改为toroman/2返回罗马数字而不是仅打印它。

然后您就可以轻松地将罗马数字与调用toroman/2整数的结果进行比较。

另请注意,如果您回溯到另一个解决方案,当前的过程将循环,直到出现堆栈溢出。您应该保护每个递归调用自身的子句,仅当调用的参数为非负数时才递归,或者添加安全失败的检查作为第一个子句,例如:

roman(N):- N < 0, !, fail.
Run Code Online (Sandbox Code Playgroud)

更改 toroman/1 以返回罗马文字后,您将得到类似的内容(只需修改一下代码以返回文字作为第二个参数):

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).
Run Code Online (Sandbox Code Playgroud)

然后您可以简单地调用roman(N, R)并测试是否R与您感兴趣的罗马数字相一致。