samoloth
samoloth

Reputation: 1

Prolog - number to list of digits

I have a trouble with conversion a number to list of digits. What's wrong? Everything works well until it returns from recursion.

number_to_digits(0, [_ | _]).
number_to_digits(Number, List) :-
    Number > 0,
    NewNumber is div(Number, 10),
    Digit is mod(Number, 10),
    append([Digit], List, NewList),
    number_to_digits(NewNumber, NewList).

Upvotes: 0

Views: 510

Answers (1)

Isabelle Newbie
Isabelle Newbie

Reputation: 9378

One of the most important skills for programming in Prolog is giving really clear names to variables and predicates. Here is your second clause with variable names changed a bit:

number_to_digits(Number, Digits) :-
    Number > 0,
    RemainingNumber is div(Number, 10),
    LastDigit is mod(Number, 10),
    append([LastDigit], Digits, RemainingDigits),
    number_to_digits(RemainingNumber, RemainingDigits).

For example, if Number is 123, then its LastDigit is 3, and the RemainingNumber after splitting off the LastDigit is 12.

Assuming that number_to_digits works correctly, RemainingDigits should then be [1, 2]. So your append call is:

append([3], Digits, [1, 2])

but this cannot have any solutions. Rather, the digits of 123 can be obtained by calling:

append([1, 2], [3], Digits)

So your code should read:

append(RemainingDigits, [LastDigit], Digits)

If you correct your first clause as well (are the digits of 0 really any non-empty list?), then this allows you to make progress:

?- number_to_digits(123, Digits).
Digits = [1, 2, 3] ;
% nontermination

This finds the correct solution, but it goes into an infinite search when you ask it for more answers. This is because there is not enough information about RemainingDigits at the time of the append call, so Prolog tries longer and longer lists. The problem is fixed if you swap the last two goals, i.e., put the append call after the recursive number_to_digits call:

?- number_to_digits(123, Digits).
Digits = [1, 2, 3] ;
false.

When asking for more answers, Prolog now correctly tells us that there are no more.

Upvotes: 2

Related Questions