SWI-Prolog谓词示例第2部分

时间:2014-05-01 19:32:30

标签: prolog

有人可以帮助我改变这个以符合这个更新的要求吗?

  

定义一个谓词strikeDuplicates(X,Y),当且仅列出Y时,它会成功   如果要删除每个元素的第二次和随后的出现,则获得   来自列表X。 (您可以将strikeDuplicates (X,Y)视为列表X而不重复   是列表Y)当strikeDuplicates/2X时,strike(X,Y,Z)谓词无法正常工作   未绑定的变量。

两天前我问了一个类似的问题:

  

定义谓词Z,当且仅当列表X成功时才成功   如果要从列表Y中删除所有出现的元素strike/3,则获取。该   当Y是未绑定的变量时,strike( _ , [] , [] ) . strike( X , [X|T] , Z ) :- strike(X,T,Z) . strike( X , [A|T] , [A|Z] ) :- dif(X,A) , strike(X,T,Z) . dif(X,A). 谓词不能正常工作。

没有人帮助我,所以我必须自己做。答案是这样的:

{{1}}

2 个答案:

答案 0 :(得分:1)

嗯,简单的方法是使用内置的谓词setof/3,但我怀疑这不是你教授想要的。

考虑一两秒钟的问题。明确的问题陈述通常很有帮助(在Prolog中通常是解决方案本身):

要使源列表成为 set (唯一元素)而不是 bag (允许复制),您必须

  • 迭代源列表
  • 跟踪您已经看过的项目(“已访问”列表)
  • 仅当访问列表尚未包含访问列表时,才将每个项目添加到访问列表。

一旦你做完了,你就得到了理想的结果。

这是一个提示:一个非常常见的prolog习语是使用带有累加器辅助谓词。帮助器谓词通常具有相同的仿函数,但是具有不同的 arity 。例如,要对列表中的值求和(sum/2),我们可以使用带有累加器的帮助器sum/3,其中加上0:

sum(Xs,N) :- sum(Xs,0,N).

sum([],S,S).
sum([N|Ns],T,S) :-
  T1 is T+N,
  sum(Ns,T1,S)
  .

在计算出最终值之前,您会注意到结果是否延迟

您需要做类似的事情,但使用[empty] 列表作为累加器,将使用您发现的唯一值进行扩展。

另一个提示:内置谓词member/2将检查一个术语是否是列表的成员。它是写的

member(X,[X|Xs]).
member(X,[_|Xs]) :- member(X,Xs).

所以member(2,[1,2,3])truemember(2,[1,3])false

相反,可以使用member/2通过回溯连续返回列表中的每个元素:member(X,[1,2,3])生成

X = 1 ;
X = 2 ;
X = 3 ;
false

鉴于这两个概念,您应该能够找到解决方案。回来向我们展示您的代码,我们可以帮助您。还有一个小gotcha,但我相信你会弄明白的。

答案 1 :(得分:1)

不保留顺序的简单解决方案是:

strike_duplicates([], []).
strike_duplicates([X| Xs], List) :-
    (   member(X, Xs) ->
        strike_duplicates(Xs, List)
    ;   List = [X| Tail],
        strike_duplicates(Xs, Tail)
    ).

要保留顺序,您需要在遍历列表时跟踪到目前为止找到的元素。解决方案是:

strip_duplicates(List, Set) :-
    strip_duplicates(List, [], Set).

strip_duplicates([], _, []).
strip_duplicates([X| Xs], Found, List) :-
    (   member(X, Found) ->
        strip_duplicates(Xs, Found, List)
    ;   List = [X| Tail],
        strip_duplicates(Xs, [X| Found], Tail)
    ).

谓词member/2通常是内置谓词或可用作库谓词。如有必要,请检查Prolog系统文档。