Per*_*age 3 element list prolog
我正在尝试编写一个谓词,如果 X 是 Y 的子列表,则该谓词为真,而不考虑 Y 的第一项和最后一项。例如,查询 listWithinList([b,c,d],[a, b,c,d,e]) 将返回 True,但查询 listWithinList([b,c,d,e],[a,b,c,d,e]) 将产生 False,因为 e,Y 的最后一个元素, 不应该是 X 的一部分。
目前我有,
listWithinList(X,Y):-append(_,Y2,Y), append(X,_,Y2).
但我不确定如何更改代码以使其执行相同的技巧,但不考虑 Y 的第一项和最后一项。
当您将_参数写入时append,它指的是一个任意列表。如此任意以至于它的长度也是任意的。
例如:
?- append(_, Suffix, [a, b, c]).
Suffix = [a, b, c] ;
Suffix = [b, c] ;
Suffix = [c] ;
Suffix = [] ;
false.
Run Code Online (Sandbox Code Playgroud)
这里_可以代表任何列表[],[a],[a, b],[a, b, c]。但我不需要告诉你这些。如果你给匿名变量_一个正确的名字,Prolog 可以告诉你这一点:
?- append(Prefix, Suffix, [a, b, c]).
Prefix = [],
Suffix = [a, b, c] ;
Prefix = [a],
Suffix = [b, c] ;
Prefix = [a, b],
Suffix = [c] ;
Prefix = [a, b, c],
Suffix = [] ;
false.
Run Code Online (Sandbox Code Playgroud)
相反,该术语[_]不代表任意列表。它代表一个绝对只有一个元素的列表。该元素(表示为_)是任意的。
例如:
?- append([_], Suffix, [a, b, c]).
Suffix = [b, c].
Run Code Online (Sandbox Code Playgroud)
或者,再次使用适当的变量名称,以便我们可以看到绑定:
?- append([X], Suffix, [a, b, c]).
X = a,
Suffix = [b, c].
Run Code Online (Sandbox Code Playgroud)
所有这一切都是说从问题的定义:
listWithinList(X,Y):-append(_,Y2,Y), append(X,_,Y2).
Run Code Online (Sandbox Code Playgroud)
接近正确。但是这两种用法_不会“删除”一个元素。它们各自“删除”任意数量的元素。所以你不只是得到列表的中间:
?- listWithinList(Middle, [a, b, c, d, e]).
Middle = [] ;
Middle = [a] ;
Middle = [a, b] ;
Middle = [a, b, c] ;
Middle = [a, b, c, d] ;
Middle = [a, b, c, d, e] ;
Middle = [] ;
Middle = [b] ;
Middle = [b, c] ;
Middle = [b, c, d] ;
Middle = [b, c, d, e] ;
Middle = [] ;
Middle = [c] ;
Middle = [c, d] ;
Middle = [c, d, e] ;
Middle = [] ;
Middle = [d] ;
Middle = [d, e] ;
Middle = [] ;
Middle = [e] ;
Middle = [] ;
false.
Run Code Online (Sandbox Code Playgroud)
如果我们想从前面和后面“删除”一个元素的列表,我们必须写[_]:
listWithinList(X, Y) :-
append([_], Y2, Y),
append(X, [_], Y2).
Run Code Online (Sandbox Code Playgroud)
现在的行为如下:
?- listWithinList(Middle, [a, b, c, d, e]).
Middle = [b, c, d] ;
false.
Run Code Online (Sandbox Code Playgroud)
此外,需要注意的区别[_]和[_|_]。前者代表只有一个元素的列表。后者代表一个或多个元素的列表。在这种情况下,您不想“删除”多个元素,因此使用[_|_],就像其他答案之一建议的那样,绝对是无稽之谈。
最后,Prolog 可以向我们建议进一步简化:
?- append([X], Xs, Ys).
Ys = [X|Xs].
Run Code Online (Sandbox Code Playgroud)
附加一个单元素列表[X]和一个任意列表Xs给出了一个列表,我们也可以[X | Xs]不使用append. 所以append不需要其中一个调用。我可以这样写这个谓词:
list_middle(List, Middle) :-
append([_First | Middle], [_Last], List).
Run Code Online (Sandbox Code Playgroud)
并像这样使用它:
?- list_middle([a, b, c, d, e], Middle).
Middle = [b, c, d] ;
false.
Run Code Online (Sandbox Code Playgroud)
或者像这样:
?- list_middle(List, [1, 2, 3]).
List = [_2658, 1, 2, 3, _2664].
Run Code Online (Sandbox Code Playgroud)