我想计算列表中的一个元素并停止计算不同元素出现的位置,然后跳转到下一个相同的元素。
答案应该是这样的:
?- 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).
我不知道如何让它返回一个数字列表。 谁能帮我? 感谢。
答案 0 :(得分:3)
以下是您可以执行此操作并保留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]].
运行列表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
- 运行列表)映射到相应的运行长度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), % works for _any_ item E maplist(length,Xs2,Xs).
让我们运行一些查询:
?- 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) .
答案 1 :(得分:1)
我的回答中的想法是保持run lengths列表打开,并在运行结束时为其添加新元素:
count(_, [], []).
count(Item, [Head|Tail], Counts) :-
count(Item, [Head|Tail], 0, Counts).
count(_, [], CurrentCount, [CurrentCount]).
count(Item, [Item|Tail], CurrentCount, Counts) :-
CurrentCountP1 is CurrentCount + 1,
count(Item, Tail, CurrentCountP1, Counts).
count(Item, [Head|Tail], CurrentCount, [CurrentCount|Counts]) :-
dif(Head, Item),
count(Item, Tail, 0, Counts).
?- count(a,[a,a,a,b,a,b,a,a,b,a,a,a,a], X).
X = [3, 1, 2, 4] ;
false.