Prolog 数字到单词

Prolog Numbers to Words

我正在使用以下谓词将数字转换为单词:

word(0) :- write('zero').
word(1) :- write('one').
word(2) :- write('two').
word(3) :- write('three').
word(4) :- write('four').
word(5) :- write('five').
word(6) :- write('six').
word(7) :- write('seven').
word(8) :- write('eight').
word(9) :- write('nine').
dash(X) :- 
    write('-'). %need to add some code here to not print dash after last dig
    

num_words(Nums) :- 
    Nums > 0,
    NMod is Nums mod 10,
    NDiv is Nums // 10,     
    word(NMod),
    dash(Nums), 
    num_words(NDiv).

期望输出:

num_words(123) => one-two-three

当前输出:

num_words(123) => three-two-one-

看看我的输出,看起来我的逻辑几乎是正确的,但我没能掌握如何更改递归来打印数字 "backwards" 以便它们按正确的顺序排列以及如何更改我的 dash(x) 谓词,使其在最后一位数字后不打印破折号。

你们对如何解决这个问题有什么建议吗?

解决第一个或最后一个动作必须与其余动作不同的问题的技巧是将谓词一分为二。在这种情况下,您可以创建调用 word(digit) 的顶级谓词,然后调用另一个打印您号码的 "tail" 的谓词,始终在数字后添加破折号。

此外,您需要重新安排递归,以便较晚计算的数字较早打印。

num_words(Nums) :-       % This is top-level predicate.
    NDiv is Nums // 10,  % It prints the first digit unconditionally,
    dash_num_words(NDiv),% letting you handle the case when the number is zero.
    NMod is Nums mod 10, 
    word(NMod).

dash_num_words(0).       % When we reach zero, we stop printing.

dash_num_words(Nums) :-  % Otherwise, we follow your algorithm
    Nums > 0,            % with one modification: the dash is printed
    NDiv is Nums // 10,  % unconditionally before printing the digit.
    dash_num_words(NDiv),
    NMod is Nums mod 10,
    word(NMod),
    write('-').

Demo.

使用这个post:Split a number into a list of digits in Prolog你只需要使用递归谓词来打印结果列表。

word('0') :- write('zero').
word('1') :- write('one').
word('2') :- write('two').
word('3') :- write('three').
word('4') :- write('four').
word('5') :- write('five').
word('6') :- write('six').
word('7') :- write('seven').
word('8') :- write('eight').
word('9') :- write('nine').

num_words(X):- number_chars(X,C), printout(C).

printout([N]):- word(N),!.
printout([N|Tail]):- word(N),write('-'),printout(Tail).

咨询:

?- num_words(1234567890).
 one-two-three-four-five-six-seven-eight-nine-zero
true.

我还更改了用引号括起数字的事实词。如果您不喜欢,我们可以更改它。

请参阅 this other answer,了解有关数字文字的更一般观点。来自消息来源:

% Grammar for numbers, e.g.
% phrase(number(I),[two,hundred,and,fifty,six]).
% An astonishing characteristic of this code is that it's
% fully bidirectional. The expression
% phrase(number(256),Words)
% will instantiate Words = [two,hundred,and,fifty,six].
% What's more,
% phrase(number(I),Words)
% will eventually instantiate I and Words to all the numbers it knows.
%
% Ken Johnson 17-9-87