删除列表中的前导s(s(0))

时间:2016-10-04 21:44:28

标签: prolog prolog-coroutining

(这是that question)的后续内容。

如何写lead1(Xs,Ys)这是真的,如果YsXs的后缀,并删除了所有前导s(s(0))个术语。因此,现在的问题不是删除前导0,而是删除前导s(s(0))

与原始问题相比,困难在于正确处理s(X)s(s(X))的案例。

2 个答案:

答案 0 :(得分:4)

以下是包含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 = [] ;
.
.
.

答案 1 :(得分:2)

Hiere是我对上一个问题的回答的改编。它显示使用when / 2而不是freeze / 2。冻结/ 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).

以下是一些示例运行,我正在选择类似的示例,就像我在回答中给出的答案一样。我们看到当list参数逐渐被实例化时,/ /何时适应自己的条件:

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

冻结/ 2,当/ 2是校对基元时。它们的纯度在文献中有很好的记载。根据这个source,第一个带有corouts的Prolog系统是Prolog-II及其geler / 2原语。该消息来源还提到了对bootstrap约束求解器进行验证的重要性。

假设纯度是用交换性测试的,这是一个样本测试:

?- 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 Extension和导入库(术语/暂停)。