编写一个包含三个参数的递归Prolog谓词,称为common,它返回属于这两个列表的元素数
编写一个包含三个参数的递归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).
?- 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).