list prolog run-length-encoding

list - contar sucesiones sucesivas de número en Prolog



run-length-encoding (5)

¿Por qué está estableciendo una relación entre dos listas con un predicado que tiene 4 argumentos? Tratemos de proceder paso a paso.

Una lista vacía da una lista vacía, un elemento contado se incrementa, de lo contrario, comienza a contar ...

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]].

tan fácil (por supuesto, suponiendo que X = [[1,3,], [2,3], [1,3] [1,2]] es un error tipográfico ...)

Hola, estoy intentando hacer un programa en Prolog que, dada una lista, cuente las ocurrencias de cada elemento sucesivo en la lista de la siguiente manera:

count(1,[1,1,1,2,2,2,3,1,1],0,X)

el resultado sería X=[ [1,3],[2,3],[3,1][1,2] ] aka cada sublista es [element,occurrences]

En mi caso, creo que hay algo mal con el caso base, pero no puedo resolverlo. ¿Me puedes ayudar?

%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).


Otra solución (cola recursiva) es esta:

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 . %


Si saltamos el uso de "es" podemos tener una solución como:

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).

eso permite no solo la consulta habitual:

[debug] ?- count([1,1,1,2,2,2,3,1,1],R). R = [ (1, 3), (2, 3), (3, 1), (1, 2)].

sino también el reverso:

[debug] ?- count(X, [ (1, 3), (2, 3), (3, 1), (1, 2)] ). X = [1, 1, 1, 2, 2, 2, 3, 1, 1].


¡Aquí hay otro intento de hacer una codificación de longitud de ejecución, basada en clpfd !

:- use_module(library(clpfd)).

En if_/3 de if_/3 y (=)/3 , definimos 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))).

Consultas de muestra:

  • codificar / decodificar # 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.

  • codificar / descodificar # 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.

  • ¿Qué tal algo un poco más general?

    ?- 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).


¡Podemos abordar su problema y preservar la pureza lógica !

A continuación, deje Xs ser [1,1,1,2,2,2,3,1,1] , la lista que utilizó en su pregunta.

Primero , Yss Xs a una lista de listas Yss tal que cada lista Ys en Yss solo contiene elementos iguales tomados de Xs . Hacemos eso usando el meta-predicate splitlistIfAdj/3 en tándem con el predicado de desigualdad reified 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]].

Segundo , Yss la lista de listas Yss a Zss . Cada elemento en Zss tiene la forma [Element,Amount] . Mirando la respuesta de la consulta anterior, vemos que todo lo que tenemos que hacer es asignar [ 1 , 1 , 1 ] a [ 1 , 3 ] , [ 2 , 2 , 2 ] a [ 2 , 3 ] , [ 3 ] para [ 3 , 1 ] y [ 1 , 1 ] a [ 1 , 2 ] . run_pair/2 hace exactamente eso:

run_pair(Ys,[Element,Amount]) :- Ys = [Element|_], length(Ys,Amount).

run_pair/2 para asignar cada elemento de Yss , con la ayuda de meta-predicate maplist/3 :

?- 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]].

¡Hecho! Es hora de poner todo junto:

count(Xs,Zss) :- splitlistIfAdj(dif,Xs,Yss), maplist(run_pair,Yss,Zss).

Veamos si la consulta anterior todavía funciona :)

?- count([1,1,1,2,2,2,3,1,1],Zss). Zss = [[1,3],[2,3],[3,1],[1,2]]. % succeeds deterministically

Como la implementación de count/2 es monótona , obtenemos respuestas lógicamente sólidas incluso cuando se trabaja con términos no terrestres. ¡Veamos eso en acción!

?- Xs = [A,B,C,D], count(Xs,Zss). Xs = [D,D,D,D], A=B, B=C , C=D , Zss = [ [D,4]] ; Xs = [C,C,C,D], A=B, B=C , dif(C,D), Zss = [ [C,3],[D,1]] ; Xs = [B,B,D,D], A=B, dif(B,C), C=D , Zss = [ [B,2], [D,2]] ; Xs = [B,B,C,D], A=B, dif(B,C), dif(C,D), Zss = [ [B,2],[C,1],[D,1]] ; Xs = [A,D,D,D], dif(A,B), B=C , C=D , Zss = [[A,1], [D,3]] ; Xs = [A,C,C,D], dif(A,B), B=C , dif(C,D), Zss = [[A,1], [C,2],[D,1]] ; Xs = [A,B,D,D], dif(A,B), dif(B,C), C=D , Zss = [[A,1],[B,1], [D,2]] ; Xs = [A,B,C,D], dif(A,B), dif(B,C), dif(C,D), Zss = [[A,1],[B,1],[C,1],[D,1]].