una resultados repetir repetidos recorrer lista eliminar elementos ejercicios duplicar contar list prolog

resultados - Empaquetar duplicados consecutivos de elementos de lista en sublistas



no repetir resultados en prolog (5)

Su cuarta cláusula intenta agregar [H|HS] al resultado, que es incorrecto, porque [H|HS] es la cola de la lista original. Puedes hacerlo mucho más simple -

pack([H, H|HS], [[H|TFR]|TR]):- pack([H|HS], [TFR|TR]).

Esencialmente, dice que cuando las dos primeras entradas son las mismas en la entrada, la primera entrada (es decir, H ) debe estar preincorporada a la primera entrada de la lista de salida producida por la invocación recursiva de la regla del pack .

Tenga en cuenta que la tercera cláusula también se puede simplificar reemplazando el parámetro Liste que "rompe" de inmediato con la versión "rajada" "insertada" en el encabezado de la cláusula, y haciendo lo mismo con la variable de salida Ergebnis1 . La versión final debería verse así:

pack([H, T|TS], [[H]|TR]):- H /= T, pack([T|TS], TR).

Aquí hay una demostración en ideone.

Necesito algo de ayuda. Busqué en la base de datos y encontré una pregunta ya hecha sobre este ejemplo, pero las respuestas realmente no me ayudaron, así que pensé en publicar mi propia pregunta.

La tarea es empacar duplicados consecutivos de elementos de lista en sublistas:

% ?- pack([a,a,a,a,b,c,c,a,a,d,e,e,e,e],X). % X = [[a,a,a,a],[b],[c,c],[a,a],[d],[e,e,e,e]].

Esto es lo que obtuve:

pack([], []). pack([X], [[X]]). pack(Liste, Ergebnis):- Liste = [H, T|TS], H /= T, pack([T|TS], Ergebnis1), append([[H]], Ergebnis1, Ergebnis). pack([H, H|HS], Ergebnis):- pack([H|HS], Ergebnis1), append([H|HS], Ergebnis1, Ergebnis).

El primer caso funciona muy bien (caso donde H / = T). El segundo no, y realmente no sé por qué. ¿Podría alguien ayudarme y explicar el problema de acuerdo con mi solución?

Gracias


Me gustaría abordar el problema de forma un poco diferente y descomponer el problema en dos tareas más simples.

Primero necesitamos poder dividir la lista en un prefijo que consista en la lista de elementos consecutivos a la cabeza de la lista y su sufijo (todo lo demás):

partition( [] , [] , [] ) . partition( [X] , [X] , [] ) . partition( [X,Y|Z] , [X] , [Y|Z] ) :- X /= Y . partition( [X,Y|Z] , [X|P] , S ) :- X = Y , partition([Y|Z],P,S) .

Una vez que tenemos eso, el resto es fácil:

pack([],[]) . % packing an empty list yields the empty list pack([X|Xs],[P,Ps]) :- % packing a non-empty list consists of partition([X|Xs],P,T) , % - partitioning it into its prefix and suffix, and pack(T,Ps) % - packing the suffix . %


Las dos primeras cláusulas son casos triviales y se ven bien.

La tercera cláusula parece razonable. Dice que si empaqué [H,T|TS] y H /= T , entonces el resultado sería [H] antepuesto al resultado de [T|TS] estaba siendo empaquetado.

La cuarta cláusula es el problema:

pack([H, H|HS], Ergebnis):- pack([H|HS], Ergebnis1), append([H|HS], Ergebnis1, Ergebnis).

Dice que el resultado del empaquetamiento [H,H|HS] es lo mismo que empacar [H|HS] y luego anteponer todo [H|HS] . Eso no parece lógico. Lo que va a pasar cuando empaques [H|HS] es que vas a obtener algo que se ve así: [[H,...,H]|X] y ahora quieres poner otra H en la cabeza del primera sublista Entonces deberías tener:

pack([H, H|HS], Ergebnis):- pack([H|HS], [HH|T]), Ergebnis = [[H|HH]|T].

Puede hacer estos predicados un poco más compactos:

pack([], []). pack([X], [[X]]). pack([H,T|TS], [[H]|PTS]):- H /= T, pack([T|TS], PTS). pack([H, H|HS], [[H|HH]|T]):- pack([H|HS], [HH|T]).

Pruebas...

| ?- pack([a,a,a,a,b,c,c,a,a,d,e,e,e,e],X). X = [[a,a,a,a],[b],[c,c],[a,a],[d],[e,e,e,e]] ? a no | ?-


Para evitar agregar, puede usar dcg :

pack(L, LP) :- % pack/2 phrase(pack(L), LP). pack([]) --> []. % pack//1 pack([X]) --> [[X]]. pack([H, H1 | T]) --> {H /= H1}, [[H]], pack([H1 | T]). pack([H, H | T]) --> pack([H | T], [H]). pack([H, H | T], P) --> % pack//2 pack([H | T], [H|P]). pack([H, H1 | T], P) --> {H /= H1}, [[H | P]], pack([H1 | T]). pack([H, H], P) --> [[H,H|P]].


Cada una de las otras implementaciones dadas en las respuestas a esta pregunta es lógicamente impura . No son monótona y, por lo tanto, se vuelven lógicamente poco sólidos cuando se usan con términos no terrestres.

La implementación sugerida aquí es lógicamente pura . Utiliza el meta-predicate splitlistIfAdj / 3 , que se basa en if_/3 , tal como lo propuso @false en una respuesta sobre reificación .

Entonces usemos splitlistIfAdj/3 en tándem con dif/3 que es una variante reificada de dif/2 :

?- splitlistIfAdj(dif,[a,a,a,a,b,c,c,a,a,d,e,e,e,e],Lists). Lists = [[a,a,a,a],[b],[c,c],[a,a],[d],[e,e,e,e]]. % succeeds deterministically

Como nos mantenemos monótona aquí, obtenemos respuestas significativas incluso si usamos términos no terrestres:

?- splitlistIfAdj(dif,[A,B,C],Lists). A = B, B = C, Lists = [[C, C, C]] ; A = B, dif(B,C), Lists = [[B, B], [C]] ; dif(A,C), B = C, Lists = [[A], [C, C]] ; dif(A,B), dif(B,C), Lists = [[A], [B], [C]].