3

如何确定两个列表在序言中是否具有相同的元素?如果我有两个列表 A 和 B,我想知道它们是否具有相同的元素。

4

5 回答 5

3

你需要写一个谓词。您可能会发现内置的 prologmember/2很有用。

如果不给出答案,很难再说什么。想一想。你会明白的。

于 2009-11-17T11:20:16.443 回答
1

我们从基于内置谓词的纯实现开始member/2

common_member(Xs,Ys) :-
   member(E,Xs),
   member(E,Ys).

示例查询:

?- common_member([1,2,3],[1]).
  true
; false.

?- common_member([1,2,3],[4]).
false.

?- common_member([1,2,3],[2,3,1]).
  true
; true
; true
; false.

声明式地,上面的代码是可以的。但是,它在成功时会留下无用的选择点。此外,如果两个列表中存在多个项目,我们会得到多余的答案。

我们能否在保持逻辑纯洁的同时提高上述效率方面? 是的!

但是怎么做?通过if_/3与具体化的测试谓词一起使用memberd_t/3

common_memberd([X|Xs],Ys) :-
   if_(memberd_t(X,Ys), true, common_memberd(Xs,Ys)).

让我们再次运行上面的示例查询,这次是common_memberd/2

?- common_memberd([1,2,3],[1]).
true.

?- common_memberd([1,2,3],[4]).
false.

?- common_memberd([1,2,3],[2,3,1]).
true.

冗余答案已被消除,随后的查询确定性地这样做。

请注意,这common_memberd/2是纯粹的,因此即使对于非常一般的查询,我们也会得到正确的答案!

?- common_memberd([1,2,3],[A,B]).
      A=1
; dif(A,1),                         B=1
;               A=2 ,           dif(B,1)
; dif(A,1), dif(A,2),                         B=2
;                         A=3 , dif(B,1), dif(B,2)
; dif(A,1), dif(A,2), dif(A,3),                     B=3
; false.
于 2015-06-20T18:22:59.413 回答
1

怎么用intersection/3

doesIntersect(X,Y) :-
    intersection(X,Y,Z),
    dif(Z,[]).

如果intersection/3产生一个空列表,那么这些列表没有共同点,结果为假。

intersection/3member/2递归调用:

intersection([X|Tail],Y,[X|Z]) :-
    member(X,Y),
    intersection(Tail,Y,Z).
intersection([X|Tail],Y,Z) :-
    \+ member(X,Y),
    intersection(Tail,Y,Z).
intersection([],_,[]).

资源。

于 2015-06-23T10:30:33.847 回答
0

您可以首先构建一个谓词differs/2来验证列表中的任何元素A是否不是列表的成员B。如果你能找到A满足这个条件的元素,那么你就可以肯定它A不包含在B. 这实际上更容易尝试验证 的每个元素A是否存在于B.
使用内置谓词member/2differs/2将如下所示:

differs(T, Q):- 
         member(X,T), 
         not( member(X, Q)). 

现在要证明两个列表都包含相同的元素,您只需要验证它们不包含differs。使用 @repeat 使用的相同谓词名称(好奇,现在谁在重复?),这是我的common_memberd\2谓词:

common_memberd(T, Q):- 
                not( differs(T, Q)), 
                not( differs(Q, T)).

咨询:

?- common_memberd( [2,3,4,1], [3, 1,4,2]).  
   true.  
?- common_memberd( [2,3,1,5], [3, 1,4,2]).  
   false.

注意:无论元素的顺序或它们是否重复,此解决方案都有效。

于 2015-06-22T20:53:12.420 回答
-1

让我知道这是否是您要寻找的东西:

same(T, Q) :- any(T, Q), !; any(Q, T), !.

any([X|_], [X,_]):- !.
any([X|T], Q) :- member(X, Q), !; any(T, Q), !.

如果您咨询它:

?- same([1,2,3,4], [3]).
true.

?- same([1,2,3,4], [4]).
true.

?- same([1], [1,4]).
true.

?- same([1,4], [1]).
true.
于 2009-11-18T04:42:54.793 回答