【问题标题】:Prolog, removing supersets in a list of listsProlog,删除列表列表中的超集
【发布时间】:2012-12-05 22:17:00
【问题描述】:

假设我有以下列表:

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).

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

【问题讨论】:

    标签: list prolog subset superset


    【解决方案1】:

    我正在使用 SWI-Prolog,在那里我找到了为 ordered setsrequired 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.
    

    【讨论】:

    • 非常感谢,这正是我们所需要的。我们应该更加注意默认谓词,因为这是一个很好的实现。
    • 你含蓄地提到了这一点,但这仅适用于按长度排序的集合。
    【解决方案2】:

    -您好 Xylon,我想我理解了您的想法,因此我尝试使用该想法创建了一个解决方案。在这里(让我知道它是否适合您的需求,或者它是否有错误......)

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

    %remove(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(List,LocRez,Final)

    % 如果需要,从列表本身中删除列表中的头部(在此过程中获得 Rez)

    % 将头部附加到我们的 LocRez(get 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),!.
    

    【讨论】:

    • 非常感谢您抽出宝贵时间和创建解决方案。
    猜你喜欢
    • 1970-01-01
    • 2018-04-24
    • 1970-01-01
    • 2011-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-12
    相关资源
    最近更新 更多