删除给定列表的成员,该列表出现在子列表之后

时间:2011-11-16 20:28:35

标签: prolog

我正在尝试删除Prolog中子列表[z,z,z]之后出现的列表的所有成员。 f.ex removeafterZZZ([a,b,c,z,z,z,a], X) -> X = [a,b,c,z,z,z].

我有方法子列表加入

    % first argument is a sublist of the second argument
    sublist(Sublist, List):-
       join(_List1, List2, List),
       join(Sublist,_List3, List2).


    % we get the list in third argument by joining lists from first two arguments
    join([], L, L).
    join([Head | Tail1], List2, [Head | Tail3]):-
    join(Tail1, List2, Tail3).

所以我一直在考虑3种可能的输入“选项”:

1)[]

2)类似[a,b,c],[a,b,c,z,z],其中输出自动为==输入

3)像[a,b,c,z,z,z,a]

这样的东西

所以我想到了3条规则:

removeafterZZZ([],[]).   %for empty lists
removeafterZZZ(List,X) :=                   %for lists with no [z,z,z] sublist
       not ( sublist ( [z,z,z], List)) , 
       X = List.

removeafterZZZ([H|T], X) :=           %for lists with sublist [z,z,z]
       join(H, X, X),                 %join the head of list with X
       removeafterZZZ(T, X).          %call function again with tail

所以这显然不会这样,我怎么知道我是否已经将z,z,z写入输出列表?我应该用一个柜台吗?怎么样?

3 个答案:

答案 0 :(得分:1)

我认为你需要担心三个案例(所以三条规则......)

  1. 清单[]
  2. [z,z,z]
  3. 开头的列表
  4. 不以[z,z,z]
  5. 开头的非空列表

    想想如何用传统语言解决这个问题 - 你走到列表中直到它结束,或者你在中间找到[z,z,z]模式。

答案 1 :(得分:1)

如果允许使用append(它是prolog提供的标准列表谓词),这里是删除后缀的通用方法 -

% removeAfterSuff(Original List, Suffix To Remove, Result)
removeAfterSuff(X, [], X) :- !.
removeAfterSuff(X, Y, X) :- \+ sublist(Y,X).
removeAfterSuff(X, Y, Z) :- append(A, B, X), append(Y, _, B), append(A,Y,Z).

它使用了一个剪切,所以它有点难看,但是否则谓词2会在你传入[]时给出一堆结果(是的,是红色的,无论如何)。

以下是它的工作原理,如果后缀不是列表的成员,则选项2激活,X和Z相等。否则它说“有两个列表,A和B可以创建我的原始列表。第二个列表B,以我的后缀开头,然后包含所有内容(我不在乎那些东西是什么)。因为我知道A是后缀之前的所有内容,然后我的结果是与Y连接的结果。“

请注意,这会为您提供多个结果,例如

[a,b,z,z,z,a,b,z,z,z]

编辑添加:你可以删除第一行,如果你没有可用的空列表返回结果,如

removeAfterSuff([a,b,c], [], Z).
Z = []
Z = [a]
Z = [a,b]
Z = [a,b,c]

答案 2 :(得分:1)

即使是家庭作业,也已经给出了完整的答案......

remove_after([], _, []).
remove_after([H|L], P, O) :-
        (   append(P, _, [H|L])
        ->  O = P
        ;   O = [H|O1],
            remove_after(L, P, O1) ).