Пролог — номер в список цифр

#prolog

#пролог

Вопрос:

У меня проблема с преобразованием числа в список цифр. Что случилось? Все работает хорошо, пока не вернется из рекурсии.

 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).
  

Комментарии:

1. Вы добавляете его к NewList , который вы передаете рекурсивно. Но это наоборот. List является результатом , тогда как NewList будет (временным) результатом для NewNumber .

2. Я пытался поменять местами newList и List, но у меня все равно не работает.

3. number_to_digits(0,[a,b,c]) успешно

Ответ №1:

Одним из наиболее важных навыков программирования в Prolog является предоставление действительно четких имен переменным и предикатам. Вот ваше второе предложение с немного измененными именами переменных:

 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).
  

Например, если Number есть 123 , то его LastDigit есть 3 , а RemainingNumber после разделения LastDigit есть 12 .

Предполагая, что это number_to_digits работает правильно, RemainingDigits тогда должно быть [1, 2] . Итак, ваш append вызов:

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

но это не может иметь никаких решений. Скорее, цифры 123 могут быть получены путем вызова:

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

Итак, ваш код должен читать:

 append(RemainingDigits, [LastDigit], Digits)
  

Если вы также исправите свое первое предложение (действительно ли цифры 0 какого-либо непустого списка?), То это позволит вам добиться прогресса:

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

Это находит правильное решение, но оно переходит в бесконечный поиск, когда вы запрашиваете у него больше ответов. Это связано с тем, что во RemainingDigits момент append вызова недостаточно информации о, поэтому Prolog пробует все более и более длинные списки. Проблема устранена, если поменять местами последние две цели, т. Е. поместить append вызов после рекурсивного number_to_digits вызова:

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

При запросе дополнительных ответов Пролог теперь правильно сообщает нам, что их больше нет.