Пролог - Как работает эта программа - PullRequest
2 голосов
/ 26 мая 2011

У меня есть эта программа, написанная на прологическом языке. Проблема в том, что я не могу понять, как это работает.

even_number([],[]).
even_number([H|T],S):-even_number(T,W),Z is H mod 2,Z==0,S=[H|W].
even_number([_|T],S):-even_number(T,S).

Все, что он делает, это извлекает четные числа из списка и сохраняет его в другом списке. Я знаю, что это работает с использованием рекурсии, но я не могу понять шаги, которые сделаны во время выполнения. Кто-нибудь может объяснить?

Ответы [ 2 ]

2 голосов
/ 26 мая 2011

Программа состоит из трех правил, которые применяются как группа.Они работают в основном как if ... else if ... else if ... [else fail].

Первое правило: четные числа в пустом списке - это пустой список.Это достаточно просто.

Второе правило применяется, если первое правило не выполняется (т. Е. Первый аргумент не является пустым списком).Это немного сложнее, но в основном говорит, чтобы включить первый элемент списка, если он четный.Логика ломается следующим образом.Четные числа в списке, начинающиеся с H и имеющие хвост T, равны S, если все термины справа верны: что четные числа в T - это какой-то список W;что Z является остатком после деления H на 2;что Z равно нулю;и что S - это H, за которым следует W (каким бы ни было W).(Обратите внимание, что это правило было бы более эффективным, если бы первый термин был перемещен после теста Z==0.)

Если это правило не выполняется (т. Е. H нечетно), то применяется последнее правило: четные числа в списке - это четные числа в конце списка.

0 голосов
/ 26 мая 2011

Написано довольно плохо.Это может быть легче понять, если вы немного реорганизуете его и делаете его рекурсивным:

even_numbers( X , R ) :-
  even_numbers( X , [] , T ) ,
  reverse( T , R ).

even_numbers( [] , T , T ).
even_numbers( [X|Xs] , T , R ) :-
  Z is X mod 2 ,
  Z == 0 ,
  ! ,
  even_numbers( Xs , [X|T] , R ).
even_numbers( [_|Xs] , T , R ) :-
  even_numbers( Xs , T , R ).

Первый предикат, предикат even_numbers/2, является общедоступной оболочкой.Он вызывает частного помощника even_numbers/3, который возвращает список четных чисел в обратном порядке.Он отменяет это и пытается объединить его с результатом, переданным в оболочке.Вспомогательный метод делает это:

  • , если список источников пуст: объедините аккумулятор (T) с результатом.
  • , если список источников не пустой, и заголовоксписок (X) четный,
    • рекурсивно опускается в конец списка (Xs), толкая X на аккумулятор.
  • , если список источников непустой, а заголовок списка (X) нечетный,
    • рекурсивно опускается в конец списка (Xs) без изменения аккумулятора.

Но, как заметил @ André Paramés, проработайте его в отладчике, и вам станет ясно, что происходит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...