我想对列表中的一个元素进行计数,并在不同元素出现的地方停止计数,并跳转到下一个相同的元素。
答案应该是这样的:
?- count(a,[a,a,a,a,b,a,a,a],X).
X = [4,3]
?- count(a,[a,a,a,b,a,b,a,a,b,a,a,a,a],X).
X = [3,1,2,4]
我为 count/3
写的代码是:
count(_, [], []).
count(X, [X | T], N) :-
count(X, T, N1),
!,
N is N1 + 1.
count(X, [_ | T], N) :-
count(X, T, N).
我不知道如何让它返回一个数字列表。 谁能帮我? 谢谢。
最佳答案
以下是您如何做到这一点并保留 logical-purity !
在下文中,我们使用元谓词 ( 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]].
The list of runs
Xs1
contains all runs. LetXs2
contain only the ones we are interested in:?- 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]].
Almost done! At last, we map
Xs2
(a list ofE
-runs) to the respective run lengthsXs
:?- 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].
Now, let's put it all together!
count(E,Xs0,Xs) :- splitlistIfAdj(dif,Xs0,Xs1), tfilter(E+\[X|_]^(X=E),Xs1,Xs2), % works for _any_ item E maplist(length,Xs2,Xs).
Let's run some queries:
?- count(a,[a,a,a,a,b,a,a,a],Xs).
Xs = [4,3]. % succeeds deterministically
?- count(a,[a,a,a,b,a,b,a,a,b,a,a,a,a],Xs).
Xs = [3,1,2,4]. % succeeds deterministically
由于代码单调,对于更一般的查询,我们也能得到逻辑上合理的答案:
?- 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) .
关于list - 计算相同的元素序言,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26417484/