Elimina duplicados consecutivos de elementos de lista con prolog

Nov 27 2020

El problema original era encontrar una forma de obtener lo siguiente

remove([a,a,a,b,q,q,q,q,e,e,e]),X)
X = [a,b,q,e]

Respuestas

1 rajashekar Nov 28 2020 at 05:20

Podemos resolver este problema mediante una iteración a lo largo de la lista. En cualquier punto de la lista verificamos el elemento actual y el siguiente elemento, si son iguales, ignoramos el elemento actual, de lo contrario, si son diferentes, tomamos el elemento actual.

rm_dup([], []).
rm_dup([X], [X]).
rm_dup([X1, X2 | Xs], [X1 | Ys]) :-
    dif(X1, X2), rm_dup([X2|Xs], Ys).
rm_dup([X, X | Xs], Ys) :-
    rm_dup([X | Xs], Ys).

Las cláusulas primera y segunda son cláusulas base en las que no hay elementos duplicados. Las cláusulas tercera y cuarta son reglas recursivas.

En la tercera cláusula, indicamos que si la lista de entrada tiene dos valores X1y X2son diferentes dif(X1, X2), entonces mantenga el valor actual.

En la cuarta cláusula, si tenemos los mismos valores consecutivos, ignoramos el valor actual.

Las cláusulas tercera y cuarta son mutuamente excluyentes y, por lo tanto, para hacer que el predicado sea determinista es mejor combinarlas de la siguiente manera

rm_dup([X], [X]) :- !.
rm_dup([X1, X2 | Xs], Ys) :-
    dif(X1, X2) -> (rm_dup([X2 | Xs], Ys1), Ys = [X1 | Ys1]);
    rm_dup([X2 | Xs], Ys).

Aún mejor es usar la igualdad como condición y cambiar las cláusulas then y else .

rm_dup([X], [X]) :- !.
rm_dup([X1, X2 | Xs], Ys) :-
    X1 = X2 ->  rm_dup([X2 | Xs], Ys);
    rm_dup([X2 | Xs], Ys1), Ys = [X1 | Ys1].
a3yko Nov 28 2020 at 03:41

Un poco largo, pero esto lo resolvió.

delete(_,[],[]).
delete(X,[X|T],R):- delete(X,T,R).
delete(X,[H|T],[H|R]) :- delete(X,T,R).

remove([],[]).
remove([H|T], [H|R]) :- 
    member(H,T),!,
    delete(H,T,R1),
    remove(R1,R).

remove([H|T],[H|R]):-
    remove(T,R).