您好,我试图在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).
最佳答案
这是基于clpfd的游程长度编码的另一种尝试!
:-use_module(library(clpfd))。
基于if_/3
和(=)/3
,我们定义list_rle/2
:
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]
;假。
编码/解码#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)
;假。
一般的东西怎么样?
?-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)。