Удалить ведущие s(s(0)) в списке

(Это продолжение этого вопроса).

Как написать lead1(Xs,Ys) что верно, если Ys это суффикс Xs со всеми ведущими s(s(0)) сроки удалены. Таким образом, вместо удаления ведущих 0 Теперь этот вопрос касается удаления ведущих s(s(0)) s.

По сравнению с первоначальным вопросом трудность заключается здесь в s(X) а также s(s(X)) должным образом.

2 ответа

Решение

Вот версия с if_/3 и = / 3:

list_suffix([],[]).
list_suffix([X|Xs],S) :-
   if_(X=s(s(0)), list_suffix(Xs,S), S=[X|Xs]).

Запросы с первым аргументом завершаются успешно:

?- list_suffix([s(0)],S).
S = [s(0)].

?- list_suffix([s(0),s(s(0))],S).
S = [s(0), s(s(0))].

?- list_suffix([s(s(0)),s(0),s(s(0))],S).
S = [s(0), s(s(0))].

?- list_suffix([s(s(0)), s(s(0)),s(0),s(s(0))],S).
S = [s(0), s(s(0))].

Если список состоит из термина, отличного от s/1, скажем, f(_) второй список идентичен первому:

?- list_suffix([f(_)],S).
S = [f(_G201)].

?- list_suffix([f(_)],[]).
false.

Частично созданные списки работают также:

?- list_suffix([X, s(s(0)),s(0),s(s(0))],S).
X = s(s(0)),
S = [s(0), s(s(0))] ;
S = [X, s(s(0)), s(0), s(s(0))],
dif(X, s(s(0))).

Самый общий запрос также работает, но перечисляет ответ несправедливым образом:

?- list_suffix(X,Y).
X = Y, Y = [] ;
X = [s(s(0))],
Y = [] ;
X = [s(s(0)), s(s(0))],
Y = [] ;
X = [s(s(0)), s(s(0)), s(s(0))],
Y = [] ;
.
.
.

Однако это можно исправить, добавив префикс длины цели /2:

?- length(X,_), list_suffix(X,Y).
X = Y, Y = [] ;
X = [s(s(0))],
Y = [] ;
X = Y, Y = [_G155],
dif(_G155, s(s(0))) ;
X = [s(s(0)), s(s(0))],
Y = [] ;
X = [s(s(0)), _G79],
Y = [_G79],
dif(_G79, s(s(0))) ;
X = Y, Y = [_G155, _G158],
dif(_G155, s(s(0))) ;
X = [s(s(0)), s(s(0)), s(s(0))],
Y = [] ;
.
.
.

Hiere - это адаптация моего ответа на предыдущий вопрос. Он показывает использование когда / 2 вместо freeze/2. freeze/2 следует только условию nonvar/1 для первого аргумента. когда / 2 может следовать более сложным условиям.

lead(X, Y) :- var(X), !, freeze(X, lead(X,Y)).
lead([X|Y], Z) :- \+ ground(X), !, when(ground(X), lead([X|Y],Z)).
lead([s(s(0))|X], Y) :- !, lead(X, Y).
lead(X, X).

Вот несколько примеров, я выбираю похожие примеры, которые я дал в предыдущем ответе. Мы видим, как, когда / 2 адаптирует свое собственное условие, когда аргумент списка постепенно создается:

?- lead([s(0),s(s(0)),s(s(0)),s(0)],Y).
Y = [s(0), s(s(0)), s(s(0)), s(0)].

?- lead([s(s(0)),s(s(0)),s(s(0)),s(0)],Y).
Y = [s(0)].

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(_).
X = s(_G3686),
when(ground(_G3686), lead([s(_G3686), s(s(0)), s(s(0)), s(0)], Y)).

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(0).
X = s(0),
Y = [s(0), s(s(0)), s(s(0)), s(0)].

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(s(_)).
X = s(s(_G3713)),
when(ground(_G3713), lead([s(s(_G3713)), s(s(0)), s(s(0)), s(0)], Y)).

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(s(0)).
X = s(s(0)),
Y = [s(0)].

freeze / 2 и когда / 2 являются сопутствующими примитивами. Их чистота хорошо документирована в литературе. Согласно этому источнику, первой системой Пролог с сопроводительной структурой был Пролог-II с его примитивом гелер / 2. В источнике также упоминается важность сопряжения для загрузчиков, решающих ограничения.

Предположим, что чистота проверяется с коммутативностью, вот пример теста:

?- lead([X,s(s(0)),s(s(0)),s(0)],Y), X=s(s(0)).
X = s(s(0)),
Y = [s(0)].

?- X=s(s(0)), lead([X,s(s(0)),s(s(0)),s(0)],Y).
X = s(s(0)),
Y = [s(0)].

Но замораживание / 2 и когда / 2 необязательно гарантируют полноту, как я уже писал в своем первом ответе, нам может понадобиться что-то сделать "в конце". Значит, после запроса у нас может быть множество непослушных целей. В программировании с ограничением мы начинаем маркировку.

Также замораживайте / 2 и когда / 2 не может найти ранние сбои путем объединения целей, как это могут сделать решатели ограничений.

Приведенный выше пример работает с SWI-Prolog без какого-либо импорта, а в Jekejeke Prolog используется библиотека расширений Minlog и библиотека импорта (term/suspend).

Другие вопросы по тегам