【问题标题】:Removing consecutive elements from a list in Prolog从Prolog中的列表中删除连续元素
【发布时间】:2021-12-28 19:48:46
【问题描述】:

到目前为止,我尝试了三个独立的函数,其中一个是第一个调用的函数,另外两个决定是否将传递给我们的结果列表的元素添加到与列表头部不匹配的元素中.递归使我感到困惑,因为它使许多其他人感到困惑,所以在这里的某个地方我有一个无限循环,导致堆栈溢出。但是我不确定很多序言概念(或语法),所以我很困惑我在哪里出错了。感谢您的帮助!

append( [], X, X).                                  
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),
    !.

【问题讨论】:

    标签: list recursion prolog


    【解决方案1】:

    嗯...首先,Prolog 没有“功能”:它有 谓词

    如果我理解您的问题陈述,您想“从列表中删除连续元素”,我理解为“将相同元素的运行折叠为单个值”,因此列表如下:

    [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 进行另一次遍历才能将事物以正确的顺序放回。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多