我建立了一个谓词,它将罗马数字转换为阿拉伯数字。唯一的问题是谓词受到限制:如果我想一次转换三个以上的阿拉伯数字,它将不再起作用。
谓词应该这样工作:
?- 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/