Search code examples
stringrecursionprologintegerwords

Prolog Numbers to Words


I am working with the following predicates to convert 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).

Desired Output:

num_words(123) => one-two-three

Current Output:

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

Looking at my output, it looks like my logic is almost correct, but I am failing to grasp how to change the recursion to print the numbers "backwards" so that they are in the right order and how to alter my dash(x) predicate to not print a dash after the last digit.

Do you guys have any suggestions on how to solve this problem?


Solution

  • The trick to solving issues where the first or the last action must be different from the rest of the actions is to split your predicate in two. In this situation, you can make your top-level predicate that calls word(digit), and then calls another predicate that prints the "tail" of your number, always adding a dash after the digit.

    In addition, you need to re-arrange the recursion in such a way that the digits computed later be printed earlier.

    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.