Elimine duplicatas consecutivas de elementos de lista com prólogo

Nov 27 2020

O problema original era encontrar uma maneira de obter o seguinte

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

Respostas

1 rajashekar Nov 28 2020 at 05:20

Podemos resolver esse problema por uma iteração ao longo da lista. Em qualquer ponto da lista verificamos o elemento atual e o próximo elemento, se forem iguais, ignoramos o elemento atual, caso contrário, se forem diferentes, pegamos o elemento atual.

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

A primeira e a segunda cláusulas são cláusulas básicas nas quais não há elementos duplicados. A terceira e a quarta cláusulas são regras recursivas.

Na terceira cláusula, afirmamos que se a lista de entrada tiver dois valores X1e X2forem diferentes dif(X1, X2), mantenha o valor atual.

Na quarta cláusula, se tivermos os mesmos valores consecutivos, ignoramos o valor atual.

A terceira e a quarta cláusulas são mutuamente exclusivas e, portanto, para tornar o predicado determinístico, é melhor combiná-las como segue

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

Melhor ainda é apenas usar a igualdade como condição e inverter as cláusulas then e 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

Um pouco longo, mas isso resolveu.

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