Prolog - 删除非唯一元素

时间:2017-06-05 01:13:36

标签: prolog

我有一个谓词来检查该元素是否是列表的成员,并查看以下内容:

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

当我打电话时:? - 成员(1,[2,3,1,4]) 我明白了:

现在我必须使用它来编写谓词,它将从列表列表中删除所有非唯一元素,如下所示:

remove([[a,m,t,a],[k,a,w],[i,k,b,b],[z,m,m,c]],X).
X = [[t],[w],[i,b,b],[z,c]]

我该怎么做?

2 个答案:

答案 0 :(得分:3)

使用library(reif) SICStus | SWI

lists_uniques(Xss, Yss) :-
   maplist(tfilter(in_unique_t(Xss)), Xss, Yss).

in_unique_t(Xss, E, T) :-
   tfilter(memberd_t(E), Xss, [_|Rs]),
   =(Rs, [], T).

注意虽然没有限制如何命名谓词,但非关系,命令式名称通常隐藏了背后的纯粹关系。 remove是一个真正的命令,但我们只想要一个关系。列表列表与仅包含唯一元素的列表列表之间的关系。

示例用法:

?- lists_uniques([[X,b],[b]], [[X],[]]).
dif(X, b).

因此,在这种情况下,我们将X保留为未实例化的变量。因此,Prolog计算出最常见的答案,找出X的样子。

(请注意,在这种情况下,您接受的答案错误地失败了)

答案 1 :(得分:1)

通过你的例子和@false的评论,实际的问题似乎是从每个子列表中删除任何其他子列表中出现的元素。我难以将其概念化为单词,这使我构建了我认为非常混乱和粗略的代码。

首先,我想要一个小帮助谓词,将member/2移动到子列表列表。

in_sublist(X, [Sublist|_])  :- member(X, Sublist).
in_sublist(X, [_|Sublists]) :- in_sublist(X, Sublists).

这不是一项伟大的工作,事实上我觉得应该以某种方式进行内联,因为我只是看不到自己想要自己使用它。

现在,我的初步解决方案不正确,看起来像这样:

remove([Sub1|Subs], [Res1|Result]) :-
    findall(X, (member(X, Sub1), \+ in_sublist(X, Subs)), Res1),
    remove(Subs, Result).
remove([], []).

你可以在这里看到我想要的那种主题:让我们使用findall/3来枚举子列表中的元素,然后我们可以过滤出其他列表中出现的那些。这不是很有效,输出看起来像这样。

?- remove([[a,m,t,a],[k,a,w],[i,k,b,b],[z,m,m,c]], R).
R = [[t], [a, w], [i, k, b, b], [z, m, m, c]].

因此,它开始使用[t]看起来没问题,但随后失去了[a,w]的情节,因为当我们进行第一次递归调用时,输入[a,m,t,a]无法看到。我们有几种方法可以解决它;一个聪明的人可能会形成一种拉链,我们将列表中的前面元素和后面的元素放在一起。另一种方法是在递归调用之前从所有后续列表中删除此列表中的元素。我选择了一个“更简单”的解决方案,这个解决方案更加简洁,难以阅读,但花费的时间更少。我强烈建议您研究其他可读性选项。

remove(In, Out) :- remove(In, Out, []).
remove([Sub1|Subs], [Res1|Result], Seen) :-
    findall(X, (member(X, Sub1),
                \+ member(X, Seen),
                \+ in_sublist(X, Subs)), Res1),
    append(Sub1, Seen, Seen1),
    remove(Subs, Result, Seen1).
remove([], [], _).

所以基本上现在我保持一个“看到”的名单。在递归调用之前,我将迄今为止看到的内容和此列表的元素拼接在一起。这不是特别有效,但它似乎完成了工作:

?- remove([[a,m,t,a],[k,a,w],[i,k,b,b],[z,m,m,c]], R).
R = [[t], [w], [i, b, b], [z, c]].

这让我感到非常讨厌。老实说,我很惊讶它是多么令人讨厌。我希望其他人可以找到一个更好的解决方案。

另一件需要调查的事情是DCG,它可以帮助您完成这些类型的列表处理任务。

相关问题