[英]Removing consecutive elements from a list in Prolog
到目前为止,我尝试了三个单独的函数,其中一个是第一个调用 function,另外两个决定是否将 append 元素传递给我们的结果列表,如果它与列表的头部不匹配。 递归使我感到困惑,因为它使许多其他人感到困惑,所以在这里的某个地方我有一个无限循环,导致堆栈溢出。 但是我不确定很多 prolog 概念(或语法),所以我很困惑我哪里出错了。 感谢您的帮助!
append( [X | Y], Z, [X | W]) :- append( Y, Z, W).
remove([], []).
remove([H|T], X) :-
append(X, [H], X),
remove(T, H, X),
!.
remove([Y|T], Y, X):-
remove(T, Y, X),
!.
remove([H|T], Y, X):-
append(X,[H], X),
remove(T,Y,X),
!.```
嗯...首先, Prolog 没有“功能”:它有predicates 。
如果我理解您的问题陈述,您想“从列表中删除连续元素”,我理解这意味着“将相同元素的运行折叠为单个值”,因此列表如下:
[a,b,b,b,,c,c,d,e,e,e,e]
减少到
[a,b,c,d,e]
假设是这种情况,您不需要(或不想要) append/3
。 总体方案是
像这样:
remove( [] , [] ) .
remove( [X|Xs] , Ys ) :- remove(Xs,Ts), try_add(X,Ts,Ys) .
try_add/3
负责决定是否在返回列表中添加/添加一个项目。 它也是微不足道的:
X
X
:
X
,X
添加到返回的列表中try_add( X , [] , [X] ) .
try_add( X , [T|Ts] , [T|Ts] ) :- X = T.
try_add( X , [T|Ts] , [X,T|Ts] ) :- X \= T.
将所有内容放在一起,您会得到:
remove( [] , [] ) .
remove( [X|Xs] , Ys ) :- remove(Xs,Ts), try_add(X,Ts,Ys) .
try_add( X , [] , [X] ) .
try_add( X , [T|Ts] , [T|Ts] ) :- X = T.
try_add( X , [T|Ts] , [X,T|Ts] ) :- X \= T.
这在 O(n) 时间和空间中运行。 它的缺点是它不是尾递归的,这意味着给定一个足够长的列表,它会使你的程序因堆栈溢出而崩溃。
另一种尾递归方法——在 O(n) 时间和 O(1) 空间中运行——是这样的:
remove( [] , [] ) .
remove( [X|Xs] , Ys ) :- remove(Xs, [X], Ts ), reverse(Ts,Ys) .
remove( [] , Ys , Ys ) .
remove( [X|Xs] , [T|Ts] , Ys ) :- X = T , remove( Xs , [X|Ts] , Ys ) .
remove( [X|Xs] , [T|Ts] , Ys ) :- X \= T , remove( Xs ,[X,T|Ts] , Ys ) .
它的缺点是它以相反的顺序构建返回列表,因此需要通过reverse/2
进行另一次遍历才能将事物以正确的顺序放回原处。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.