我建立了一个谓词,它将罗马数字转换为阿拉伯数字。唯一的问题是谓词受到限制:如果我想一次转换三个以上的阿拉伯数字,它将不再起作用。

谓词应该这样工作:

?- convert([v,i,i],Arabic).
Arabic = 7.

到目前为止我的解决方案:
tran([],0).
tran(i,1).
tran(v,5).
tran(x,10).

convert([],X) :- X is 0, !.
convert([T],X) :- tran(T,E), X is E,!.
convert([T|Ts],X) :- tran(T,E), tran(Ts,Es), X is E+Es,!.
convert([T,Ts,Tss],X) :- tran(T,E), tran(Ts,Es), tran(Tss,Ess), X is E+Es+Ess.

我知道为什么谓词不能使用超过3个数字,并且我还可以扩展convert-谓词,但是使用与上面所示相同的模式。

如何使转换谓词更“通用”(以便它可以独立于数字数量工作)?还是您对如何编写谓词有其他想法?
谢谢 :)

最佳答案

我没有对此进行过多测试,但是我已经在多个数字上进行了尝试,并且似乎可以正常工作。

该代码遵守“减法对规则”,例如在https://projecteuler.net/about=roman_numerals中描述

该代码使用“累加器”技术来传递信息,该信息是之前看到的数字总和。初始调用只是将累加器设置为0。

digit(i, 1).
digit(v, 5).
digit(x, 10).
digit(l, 50).
digit(c, 100).
digit(d, 500).
digit(m, 1000).

convert(Roman, Arabic) :-
    convert(Roman, 0, Arabic).

convert([], Acc, Acc).

convert([A], Acc, Arabic) :-
    digit(A, AVal),
    Arabic is Acc + AVal.

convert([A, B | Rest], Acc, Arabic) :-
    digit(A, AVal), digit(B, BVal),
    AVal < BVal,
    NewAcc is Acc + BVal - AVal,
    convert(Rest, NewAcc, Arabic).

convert([A, B | Rest], Acc, Arabic) :-
    digit(A, AVal), digit(B, BVal),
    AVal >= BVal,
    NewAcc is Acc + AVal,
    convert([B | Rest], NewAcc, Arabic).

一些测试:
convert([v, i, i], Arabic).
Arabic = 7

?- convert([x, i, x], Arabic).
Arabic = 19

?- convert([m, d, c, v, i], Arabic).
Arabic = 1606

可以使用约束编程编写一个谓词convert以真正的Prolog精神双向运行,但是我还没有尝试过这种方法。

关于math - 将罗马数字翻译成阿拉伯数字,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21538970/

10-12 00:37
查看更多