Prolog,删除列表列表中的超集

时间:2012-12-05 22:17:00

标签: list prolog subset superset

假设我有以下列表:

List = [[a],[a,b],[a,c],[b,c],[b,d],[a,b,c],[a,b,d],[b,c,e],[b,d,e,f]]

目标是删除列表中列表中列表的超集的每个列表。

包含列表的列表始终具有以下属性:

  • 列表中的列表按长度排序
  • 列表中的每个列表都已排序

我最初的想法是简单地从列表中的第一个列表开始,然后浏览所有其他列表并删除作为超集的列表。接下来我会看第二个清单,等等。

删除列表[a]的所有超集后,它应如下所示:

List = [[a],[b,c],[b,d],[b,c,e],[b,d,e,f]]

接下来应删除[b,c]的超集:

List = [[a],[b,c],[b,d],[b,d,e,f]]

最后是[b,d]的超集:

List = [[a],[b,c],[b,d]]

上面的行应该是结果。

我已经创建了一个类似于成员谓词的谓词,但它没有采用单个元素并将其与列表进行比较,而是采用整个列表并将其与列表进行比较:

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

这仅适用于列表。

?- memberList(a,[a,b,c]).
false.

?- memberList([a],[a,b,c]).
true .

?- memberList([a,b],[a,b,c]).
true .

但在此之后我有点迷失了。

我尝试了以下哪个应删除单个集的超集,但它不起作用:

removeSupersetsList(_,[],[]).
removeSupersetsList(X,[Y|Ys],[Y|Out]) :-
    not(memberList(X,Y)),
    removeSupersetsList(X,Ys,Out).
removeSupersetsList(X,[Y|Ys],Out) :-
    memberList(X,Y),
    removeSupersetsList(X,Ys,Out).

所以我想知道是否有人可以指出我正确的方向从列表中删除所有超集,甚至可能给出正确的谓词。

2 个答案:

答案 0 :(得分:0)

-Hello Xylon,我想我理解了你的想法,所以我试着用这个想法创造了一个解决方案。这是(让我知道它是否适合您的需求,或者它是否有错误......)

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

%删除(ToRemove,ListWithSublists,LocRez,FinalRez)

%将删除ListWithSublists中的列表,具体取决于ToRemove

%LocRez是用于获取FinalRez的累加器(最后)

remove(_,[],LocRez,LocRez) :- !.

remove(ToRemove,ListWithSublists,LocRez,FinalRez) :-     ListWithSublists=[Sublist|Rest],
                                                         memberList(ToRemove,Sublist),
                                                         remove(ToRemove,Rest,LocRez,FinalRez),!.

remove(ToRemove,ListWithSublists,LocRez,FinalRez) :-     ListWithSublists=[Sublist|Rest],
                                                         not(memberList(ToRemove,Sublist)),
                                                         append(LocRez,[Sublist],LocRezNew),
                                                         remove(ToRemove,Rest,LocRezNew,FinalRez),!.
  

removeSupersetsList(List,Rez): - removeSupersetsList(List,[],Rez)。 %将此称为测试

<强>%removeSupersetsList(列表,LocRez,最终)

如果需要,

%从列表中删除列表中的头部(在此过程中获取Rez)

%将Head添加到我们的LocRez(获取LocRezNew),

%以递归方式调用Rez

removeSupersetsList(List,LocRez,LocRez) :- List=[] ,!.
removeSupersetsList(List,LocRez,Final) :- ( List=[ToRemove|_] ; List=[ToRemove] ),
                                          remove(ToRemove,List,[],Rez),
                                          append(LocRez,[ToRemove],LocRezNew),
                                          removeSupersetsList(Rez,LocRezNew,Final),!.

答案 1 :(得分:0)

我正在使用SWI-Prolog,我找到了ordered sets的精心制作的库,required test,然后使用select / 3,它很容易清理列表

rem_super_sets([], []).
rem_super_sets([L|Ls], R) :-
    (   select(T, Ls, L1), % get any T in Ls
        ord_subset(L, T)   % is T a superset of L ?
    ->  rem_super_sets([L|L1], R) % discard T, keep L for further tests
    ;   R = [L|L2],
        rem_super_sets(Ls, L2)
    ).

这里有验证和结果

test :-
    List = [[a],[a,b],[a,c],[b,c],[b,d],[a,b,c],[a,b,d],[b,c,e],[b,d,e,f]],
    rem_super_sets(List, R),
    write(R).

?- test.
[[a],[b,c],[b,d]]
true.