Список с, если - плюс и минус - PullRequest
0 голосов
/ 05 июня 2018

Я должен создать список с целым числом. Это должно быть ziga_arnitika (L, ML). Что возьмет L список (+) целое число и вернет список ML только (-) целое число четных чисел списка L. Предупреждение:X mod Y вычисляет X: Y.

Example: ziga_arnitika([3,6,-18,2,9,36,31,-40,25,-12,-5,-15,1],ML).
ML =[-18,-40,-12]

Я знаю, например, не со списком для использования, если не со списками, то, что я сделал, это ..:

something(12) :-
write('Go to L).
something(10) :-
write('Go to Ml).
something(other) :-
Go is other -10,
format('Go to list ~w',[ML]).

1 Ответ

0 голосов
/ 05 июня 2018

Вы хотите вычислить список с элементами, удовлетворяющими некоторым свойствам из данного списка.Списки в Прологе имеют очень простое представление.Пустой список представлен [].Непустой список - это последовательность элементов, разделенных запятой.Например, [1,2,3].Prolog также предоставляет удобную нотацию для разделения списка между его головой (или первым элементом) и хвостом (список с оставшимися аргументами):

?- [1,2,3] = [Head| Tail].
Head = 1,
Tail = [2, 3].

Прогулка по списку (от его первого элемента до последнего элемента)) можно легко сделать с помощью простого рекурсивного предиката.Тривиальный случай, когда список пуст:

walk([]).

Если список не пуст, мы переходим к хвосту списка:

walk([Head| Tail]) :- walk(Tail).

Однако, если вы попробуете это определение предикатапрактически в любой системе Prolog он предупредит вас, что Head является одноэлементной переменной .Это означает, что переменная появляется один раз в предложении предиката.Вы можете устранить предупреждение, заменив переменную Head анонимной переменной (которую мы можем интерпретировать как переменную "пофиг").Таким образом, в настоящее время мы имеем:

walk([]).
walk([_| Tail]) :- walk(Tail).

Мы можем попробовать это с нашим примером списка:

?- walk([1,2,3]).
true.

Пролог является реляционным языком, что произойдет, если мы вызовемпредикат walk/1 с переменной вместо этого?

?- walk(List).
List = [] ;
List = [_4594] ;
List = [_4594, _4600] ;
List = [_4594, _4600, _4606]
...

Теперь вернемся к исходной проблеме: построение списка из элементов другого списка.Мы хотим обработать каждый элемент списка ввода и, если он удовлетворяет некоторому свойству, добавить его в список вывода.Нам нужны два аргумента.Простой случай (или base case) снова, когда список ввода пуст:

process([], []).

Общий случай (или рекурсивный регистр) будет:

process([Head| Tail], [Head| Tail2]) :-
    property(Head),
    process(Tail, Tail2).

в предположении предиката property/1, который имеет значение true, когда его аргумент удовлетворяет некоторому свойству.В вашем случае, быть четным, отрицательным целым числом.Но не все элементы удовлетворят свойству.Чтобы справиться с этим случаем, нам нужно третье предложение, которое пропустит элемент, который не удовлетворяет свойству:

 process([Head| Tail], List) :-
    \+ property(Head),
    process(Tail, List).

Предикат \+/1 - это стандарт Пролога Предикат отрицания : этоtrue, если его аргумент равен false.

Давайте попробуем наш предикат process/2, определив предикат property/1, который будет истинным, если аргумент является целым нулем:

property(0).

Примертогда вызов будет:

?- process([1,0,2,0,0,3,4,5], List).
List = [0, 0, 0] ;
false

Мы успешно написали предикат, который извлекает все нули из списка.Обратите внимание, что наш запрос имеет одно решение .Если мы введем ; для запроса следующего решения в командной строке, интерпретатор верхнего уровня Prolog сообщит нам, что решений больше нет (точная распечатка зависит от выбранной системы Prolog; некоторые напечатают, например, noвместо false, но смысл тот же).

Можете ли вы теперь решить исходный вопрос, определив подходящий предикат property/1?

Обновление

Вы можете объединить два рекурсивных предложения в одном, написав, например:

process([Head| Tail], List) :-
    (   % condition
        property(Head) ->
        % then
        List = [Head| Tail2],
        process(Tail, Tail2)
    ;   % else
        process(Tail, List)
    ).

В этом случае мы используем стандарт Prolog if-then-else управляющую конструкцию .Обратите внимание, однако, что эта конструкция делает неявное cut в условии.Т.е. мы берем только первое решение для предиката property/1 и отбрасываем любые другие потенциальные решения.Использование этой управляющей конструкции также не позволяет использовать предикат process/2 в reverse (например, вызывать его с несвязанным первым аргументом и связанным вторым аргументом) или использовать его для генерации парусловия, которые удовлетворяют отношению (например, вызывая его с обоими аргументами, не связанными).Эти проблемы могут быть или не быть существенными в зависимости от свойства, которое вы используете для фильтрации списка, и от деталей практической проблемы, которую вы решаете.Возможны более сложные альтернативы, но они выходят за рамки этого вводного ответа.

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