【问题标题】:prolog convert numbers into roman numeralsprolog 将数字转换为罗马数字
【发布时间】:2012-10-27 12:10:47
【问题描述】:

我有这段代码可以将整数转换为罗马数字 我需要添加一个函数,将整数与罗马数字输入进行比较,并显示它是 try 还是 false,例如: 罗马(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).

【问题讨论】:

  • 试试toroman(-1):你会得到IVXXLXCCDCM。这与toroman(0+9) 的值相同。

标签: numbers prolog dcg clpfd roman-numerals


【解决方案1】:

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

:- 使用模块(库(clpfd))。 罗马(0)->“”。 罗马 (N0) --> "I", { 1 #=

你可以这样使用它:

?- 短语(罗马(3),L)。 L =“三”; 错误的。

?- 短语(罗马(N),“II”)。 N = 2; 错误的。

或者,如果您不知道该问什么,只需问最普遍的问题:

?- 短语(罗马(N),L)。 N = 0, L = []; N = 1, L = "我" ; N = 2, L = "二" ; N = 3, L =“三”; 错误的。

要像L = "III" 这样简洁地获得答案,请使用:- set_prolog_flag(double_quotes,chars). 更多信息,请参阅this answer

【讨论】:

  • 在 DCG 上使用 CLP(FD) 表达语义看起来真的很有趣!
  • @chac:SWI 中的 CLP(FD) 实际上是作为整数运算的更纯粹的替代品。
  • 它提供了如此高级的结构,它不仅仅是算术,至少实际上是这样。
  • @chac:大多数 CLP(FD) 实现具有严重的正确性和其他限制,使其无法用作替代品。
  • 是的,在普通的 Prolog 中使用 CLP(FD) 很棒。谢谢马库斯!!
【解决方案2】:

您应该将您的toroman/1 过程更改为类似toroman/2 的东西,它返回罗马数字而不是仅仅打印它。

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

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

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

在更改 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).

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

【讨论】:

  • 谢谢,这真的很有帮助。清单是我需要的。我试图修改您的代码以获得真或假的结果,例如:?-罗马(5,V)。真的。 ?-罗马(5,R)。 R=V。我应该改变什么?
  • 您必须用单引号将罗马文字括起来(因为您想使用原子,而不是变量)。因此,例如,您可以问?- roman(5, 'V')。
  • 我知道了,只需将所有大写字母改为小写
猜你喜欢
  • 1970-01-01
  • 2019-01-09
  • 2011-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-09
相关资源
最近更新 更多