Elimina duplicados consecutivos de elementos de lista con prolog
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
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 X1
y X2
son 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].
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).