以下是如何实现并保留逻辑纯度的方法!
在接下来的内容中,我们使用元谓词(splitlistIfAdj/3
, tfilter/3
和maplist/3
)和实化术语相等/不等谓词((=)/3
和dif/3
)。
假设E = a
和Xs0 = [a,a,a,b,a,b,a,a,b,a,a,a,a]
,我们逐步构建count/3
:
首先,让Xs1
包含Xs0
中项目的运行:
?- Xs0 = [a,a,a,b,a,b,a,a,b,a,a,a,a], splitlistIfAdj(dif,Xs0,Xs1).
Xs0 = [ a,a,a, b, a, b, a,a, b, a,a,a,a ],
Xs1 = [[a,a,a],[b],[a],[b],[a,a],[b],[a,a,a,a]].
运行列表Xs1
包含所有运行。让Xs2
只包含我们感兴趣的运行:
?- Xs1 = [[a,a,a],[b],[a],[b],[a,a],[b],[a,a,a,a]], tfilter(\[X|_]^(X=a),Xs1,Xs2).
Xs1 = [[a,a,a],[b],[a],[b],[a,a],[b],[a,a,a,a]],
Xs2 = [[a,a,a], [a], [a,a], [a,a,a,a]].
几乎完成了!最后,我们将Xs2
(一个E
-runs列表)映射到相应的运行长度Xs
:
?- Xs2 = [[a,a,a],[a],[a,a],[a,a,a,a]], maplist(length,Xs2,Xs).
Xs2 = [[a,a,a],[a],[a,a],[a,a,a,a]],
Xs = [ 3, 1, 2, 4].
现在,让我们把所有东西放在一起!
count(E,Xs0,Xs) :-
splitlistIfAdj(dif,Xs0,Xs1),
tfilter(E+\[X|_]^(X=E),Xs1,Xs2), % 适用于 _任何_ 项目 E
maplist(length,Xs2,Xs).
让我们运行一些查询:
?- count(a,[a,a,a,a,b,a,a,a],Xs).
Xs = [4,3].
?- count(a,[a,a,a,b,a,b,a,a,b,a,a,a,a],Xs).
Xs = [3,1,2,4].
由于代码是单调的,因此我们也可以为更一般的查询得到逻辑上正确的答案:
?- count(E,[a,a,a,b,a,b,a,a,b,a,a,a,a],Xs).
Xs = [3,1,2,4], E = a ;
Xs = [1,1,1], E = b ;
Xs = [], dif(E,a), dif(E,b) .