Search code examples
prolog

Removing consecutive duplicates from a list in Prolog


I have list like following :

[a,b,b,e,e,f,f,g]

The first and last entries are single, while all others are repeated. How can I remove these extra entries. I should not disturb the order.

I tried following but it gets an empty list:

removeDups([], []).
removeDups([H1,H2|T], Newlist) :- 
    (H1 == H2 -> removeDups([H2|T],Newlist) 
    ; removeDups(T,Newlist)).

?- removeDups([a,b,b,c,c,d,d,e],L).
L = [].

Edit: I have already checked many similar question on stackoverflow. But in my list the duplicates are consecutive and therefore a simpler solution may be possible. I could not find a question on removing consecutive duplicate entries.


Solution

  • In your predicate, the second argument should always represent the result of duplicates being removed from the first argument. That leads to the following clauses when broken down into each case:

    remove_dups([], []).   % Empty list is empty list with dups removed
    remove_dups([X], [X]). % Single element list is itself with dups removed
    
    % The result of removing duplicates from `[X,X|T]` should be the same
    %   as the result of removing duplicates from `[X|T]`
    remove_dups([X,X|T], [X|R]) :-
        remove_dups([X|T], [X|R]).
    
    % The result of removing duplicates from `[X,Y|T]` where X and Y are different
    %   should be the result [X|R] where R is the result of removing duplicates
    %   from [Y|T]
    remove_dups([X,Y|T], [X|R]) :-
        X \== Y,
        remove_dups([Y|T], R).
    

    The 3rd and 4th clauses could be replaced with:

    remove_dups([X,Y|T], [X|R]) :-
        (   X == Y
        ->  remove_dups([Y|T], [X|R])
        ;   remove_dups([Y|T], R)
        ).
    

    But then it will limit solutions where the first argument is variable.