您好我正在尝试在Prolog中创建一个程序,该程序给出一个列表,它按列表计算列表中每个连续元素的出现次数:
count(1,[1,1,1,2,2,2,3,1,1],0,X)
结果将是X=[ [1,3],[2,3],[3,1][1,2] ]
又名每个子列表是[element,occurrences]
在我的情况下,我认为基本情况有问题,但我无法解决。你能救我吗?
%append an element to a list
append([ ],Y,Y).
append([X|Xs],Ys,[X|Zs]):-append(Xs,Ys,Zs).
%c is the counter beginning with 0
count(_,[],_,[]).
count(X,[X],C,[L]):-count(X,[],C,[L|[X,C]]).
%increase counter
count(X,[X|Tail],C,L):-Z is C+1,count(X,Tail,Z,L).
count(X,[Head|Tail],C,[L]):-append(L,[X,C],NL),count(Head,Tail,1,NL).
答案 0 :(得分:2)
我们可以解决您的问题和保留logical-purity!
在下面,让Xs
为[1,1,1,2,2,2,3,1,1]
,即您在问题中使用的列表。
首先,我们将Xs
映射到列表Yss
,以便Ys
中的每个列表Yss
仅包含取自的相同元素Xs
。
我们通过将元谓词splitlistIfAdj/3
与具体化的不等式谓词dif/3
结合使用来实现这一点:
?- Xs = [1,1,1,2,2,2,3,1,1], splitlistIfAdj(dif,Xs,Yss).
Xs = [ 1,1,1, 2,2,2, 3, 1,1 ],
Yss = [[1,1,1],[2,2,2],[3],[1,1]].
第二次,我们将列表Yss
映射到Zss
。 Zss
中的每个项目都具有[Element,Amount]
形式。
查看上述查询的答案,我们发现我们需要做的就是将[1,1,1]
映射到[1,3]
,将[2,2,2]
映射到[2,3]
,将[3]
映射到{{ 1}}和[3,1]
到[1,1]
。 [1,2]
正是这样做的:
run_pair/2
在meta-predicate maplist/3
的帮助下,让我们使用run_pair(Ys,[Element,Amount]) :-
Ys = [Element|_],
length(Ys,Amount).
来映射run_pair/2
的每个项目:
?- Yss = [[1,1,1],[2,2,2],[3],[1,1]], maplist(run_pair,Yss,Zss). Yss = [[1,1,1],[2,2,2],[3] ,[1,1]], Zss = [[1,3], [2,3], [3,1],[1,2]].
完成!把时间放在一起的时间:
Yss
让我们看看上面的查询是否仍然有效:)
count(Xs,Zss) :-
splitlistIfAdj(dif,Xs,Yss),
maplist(run_pair,Yss,Zss).
由于?- count([1,1,1,2,2,2,3,1,1],Zss).
Zss = [[1,3],[2,3],[3,1],[1,2]]. % succeeds deterministically
的实施是单调,即使使用非基础术语,我们也能获得逻辑上合理的答案。让我们看看它在行动!
count/2
答案 1 :(得分:2)
这是另一种基于clpfd进行游程编码的尝试!
:- use_module(library(clpfd)).
list_rle([],[]). list_rle([X|Xs],[N*X|Ps]) :- list_count_prev_runs(Xs,N,X,Ps). list_count_prev_runs(Es,N,X,Ps) :- N #> 0, N #= N0+1, list_count_prev_runs_(Es,N0,X,Ps). list_count_prev_runs_([],0,_,[]). list_count_prev_runs_([E|Es],N,X,Ps0) :- if_(X=E, list_count_prev_runs(Es,N,X,Ps0), (N = 0, Ps0 = [M*E|Ps], list_count_prev_runs(Es,M,E,Ps))).
示例查询:
编码/解码#1
?- list_rle([a,a,b,c,c,c,d,e,e],Ys). Ys = [2*a,1*b,3*c,1*d,2*e]. ?- list_rle(Xs,[2*a,1*b,3*c,1*d,2*e]). Xs = [a,a,b,c,c,c,d,e,e] ; false.
编码/解码#2
?- dif(A,B),dif(B,C),dif(C,D),dif(D,E), list_rle([A,A,B,C,C,C,D,E,E],Ys). Ys = [2*A,1*B,3*C,1*D,2*E], dif(A,B), dif(B,C), dif(C,D), dif(D,E). ?- list_rle(Xs,[2*A,1*B,3*C,1*D,2*E]). Xs = [A,A,B,C,C,C,D,E,E], dif(A,B), dif(B,C), dif(C,D), dif(D,E) ; false.
一般情况怎么样?
?- list_rle([A,B,C,D],Xs). Xs = [4*A ], A=B , B=C , C=D ; Xs = [3*A, 1*D], A=B , B=C , dif(C,D) ; Xs = [2*A, 2*C ], A=B , dif(B,C), C=D ; Xs = [2*A, 1*C,1*D], A=B , dif(B,C), dif(C,D) ; Xs = [1*A,3*B ], dif(A,B), B=C , C=D ; Xs = [1*A,2*B, 1*D], dif(A,B), B=C , dif(C,D) ; Xs = [1*A,1*B,2*C ], dif(A,B), dif(B,C), C=D ; Xs = [1*A,1*B,1*C,1*D], dif(A,B), dif(B,C), dif(C,D).
答案 2 :(得分:1)
为什么要说明具有4个参数的谓词的两个列表之间的关系?让我们一步一步地尝试。
空列表给出一个空列表,计算的元素递增,否则,开始计数......
count([],[]).
count([X|T],[[X,C1]|R]) :- count(T,[[X,C]|R]), !, C1 is C+1.
count([X|T],[[X,1]|R]) :- count(T,R).
?- count([1,1,1,2,2,2,3,1,1],R).
R = [[1, 3], [2, 3], [3, 1], [1, 2]].
这么容易(当然,假设X = [[1,3],[2,3], [1,3] [1,2]]这是一个错字。 ..)
答案 3 :(得分:0)
另一种解决方案(尾递归)是:
run_length_encode( Xs , Ys ) :- % to find the run length encoding of a list ,
rle( Xs , 1 , Ys ) . % - just invoke the helper
rle( [] , _ , [] ) . % the run length encoding of the empty list is the empty list
rle( [A] , N , [X:N] ) . % A list of length 1 terminates the run: move the run length to the result
rle( [A,A|Xs] , N , Ys ) :- % otherwise, if the run is still going
N1 is N+1 , % - increment the count,
rle( [A|Xs] , N1 , Ys ) % - and recurse down
. %
rle( [A,B|Xs] , N , [A:N|Ys] ) :- % otherwise, if the run has ended
A \= B , % - we have a break
rle( [B|Xs] , 1 , Ys ) % - add the completed run length to the result and recurse down
. %
答案 4 :(得分:0)
如果我们跳过使用"是"我们可以有一个解决方案:
precondition(Clause):-
Clause =.. [_|ARGS],
( maplist(var,ARGS) -> true; Clause ).
count( [], [] ).
count( [X], [(X,1)] ) :- !.
count( [H|Q], [(H,1),(HR,NR)|QR] ) :-
count( Q, [(HR,NR)|QR] ),
H \= HR,
!.
count( [H|Q], [(H,NR)|QR] ) :-
precondition( succ(N,NR) ),
count( Q, [(H,N)|QR] ),
succ(N,NR).
不仅允许通常的查询:
[debug] ?- count([1,1,1,2,2,2,3,1,1],R).
R = [ (1, 3), (2, 3), (3, 1), (1, 2)].
但也反过来:
[debug] ?- count(X, [ (1, 3), (2, 3), (3, 1), (1, 2)] ).
X = [1, 1, 1, 2, 2, 2, 3, 1, 1].