编写一个包含三个参数的递归Prolog谓词,称为common,它返回属于这两个列表的元素数

编写一个包含三个参数的递归Prolog谓词,称为common,它返回属于这两个列表的元素数,prolog,logical-purity,meta-predicate,Prolog,Logical Purity,Meta Predicate,编写一个包含三个参数的递归Prolog谓词,称为common,它返回属于两个列表的元素数。 例如: ?- common ( [a, b, c, k, h], [b,c,d,e], N). N=2. ?- common ( [b, a, c, d], [a, b, c, d, e] , N). N=4. 使用内置的交叉口/3可以轻松完成: common(A, B, N) :- intersection(A, B, C), length(C, N).

编写一个包含三个参数的递归Prolog谓词,称为common,它返回属于两个列表的元素数。 例如:

   ?- common ( [a, b, c, k, h], [b,c,d,e], N).
   N=2.

   ?- common ( [b, a, c, d], [a, b, c, d, e] ,  N).
   N=4.

使用内置的
交叉口/3
可以轻松完成:

common(A, B, N) :-
    intersection(A, B, C),
    length(C, N).
试运行:

?- common([a, b, c, k, h], [b,c,d,e], N).
N = 2.

?- common([b, a, c, d], [a, b, c, d, e],  N).
N = 4.

请注意,在查询中,“common”和“(”)之间没有空格。这很重要。如您在问题中所述的查询(在“common”和“(”)之间有空格)将产生语法错误。

这是一种方法,假设您希望确保结果是一个集合(唯一项目),而不是一个包(允许重复项目):

另一种更简单的方法:

set_intersection( Xs , Ys , Zs ) :-
  set_of(Z,(member(Z,Xs),member(Z,Ys)),Zs)
  .
另一种方式:

set_intersection( Xs , Ys , Zs ) :-       % compute the set intersection by
  set_intersectin( Xs , Ys , [] , Zs ) .  % invoking the worker predicate

set_intersection( []     , _  , Zs , Zs ) .  % when we run out of Xs, we're done.
set_intersection( [X|Xs] , Ys , Ts , Zs ) :- % otherwise,
  member(X,Ys) ,                             % if X is a member of Ys,
  \+ member(X,Ts) ,                          % and we don't yet have an X,
  set_intersection( Xs , Ys , [X|Ts] , Zs )  % add X to the accumulator and recurse down
  .                                          %
保存

首先,我们定义
tcount/3
,以便对重复的列表项进行折扣。
tcount/3
类似于,但用于排除重复项:

:- meta_predicate tcountd(2,?,?). tcountd(P_2,List,Count) :- list_tcountd_pred(List,Count,P_2). :- meta_predicate list_tcountd_pred(?,?,2). list_tcountd_pred([] ,0, _ ). list_tcountd_pred([X|Xs0],N,P_2) :- if_(call(P_2,X), (N #= N0+1, N0 #>= 0), N = N0), tfilter(dif(X),Xs0,Xs), list_tcountd_pred(Xs,N0,P_2). 让我们运行OP给出的示例查询:

?- common([a,b,c,k,h],[b,c,d,e],N).
N = 2.

?- common([b,a,c,d],[a,b,c,d,e],N).
N = 4.
由于
common/3
是单调的,我们在非地面查询中也会得到合理的答案

?- common([A,B],[X,Y],N).
  N = 1,     A=B ,                         B=X
; N = 2,               A=X ,                         B=Y , dif(X,Y)
; N = 1,               A=X ,           dif(B,X), dif(B,Y)
; N = 1,     A=B ,                                   B=Y , dif(X,Y)
; N = 2,                         A=Y ,     B=X ,           dif(X,Y)
; N = 1,                         A=Y , dif(B,X), dif(B,Y), dif(X,Y)
; N = 0,     A=B ,                     dif(B,X), dif(B,Y)
; N = 1,           dif(A,X), dif(A,Y),     B=X
; N = 1,           dif(A,X), dif(A,Y),               B=Y , dif(X,Y)
; N = 0, dif(A,B), dif(A,X), dif(A,Y), dif(B,X), dif(B,Y).

//不应使用“切割”操作来表示您尝试解决此问题的方法。 common(Xs,Ys,N) :- tcountd(Ys+\X^memberd_t(X,Ys),Xs,N).
?- common([a,b,c,k,h],[b,c,d,e],N).
N = 2.

?- common([b,a,c,d],[a,b,c,d,e],N).
N = 4.
?- common([A,B],[X,Y],N).
  N = 1,     A=B ,                         B=X
; N = 2,               A=X ,                         B=Y , dif(X,Y)
; N = 1,               A=X ,           dif(B,X), dif(B,Y)
; N = 1,     A=B ,                                   B=Y , dif(X,Y)
; N = 2,                         A=Y ,     B=X ,           dif(X,Y)
; N = 1,                         A=Y , dif(B,X), dif(B,Y), dif(X,Y)
; N = 0,     A=B ,                     dif(B,X), dif(B,Y)
; N = 1,           dif(A,X), dif(A,Y),     B=X
; N = 1,           dif(A,X), dif(A,Y),               B=Y , dif(X,Y)
; N = 0, dif(A,B), dif(A,X), dif(A,Y), dif(B,X), dif(B,Y).