Why resort to solutions that can only be used in very specific cases, and yield wrong results in other cases? Imperative programming is so 1980... The 80s were cool, I know, but a bit limited too, no?
Try thinking in terms of relations that can be used in all directions!
Here is a solution that uses if_/3
for generality:
no_consecutive_duplicates([], []).
no_consecutive_duplicates([L|Ls0], Ls) :-
no_dups(Ls0, L, Ls).
no_dups([], E, [E]).
no_dups([L|Ls0], E, Ls) :-
if_(L=E, Ls=Ls1, Ls=[E|Ls1]),
no_dups(Ls0, L, Ls1).
It works also in the most general case:
?- no_consecutive_duplicates(Ls0, Ls).
Ls = Ls0, Ls0 = []
Ls = Ls0, Ls0 = [_G501] ;
Ls = [_G501],
Ls0 = [_G501, _G501] ;
Ls = [_G501],
Ls0 = [_G501, _G501, _G501] .
For fair enumeration, use for example:
?- length(Ls0, _), no_consecutive_duplicates(Ls0, Ls).
Ls = Ls0, Ls0 = [] ;
Ls = Ls0, Ls0 = [_G501] ;
Ls = [_G501],
Ls0 = [_G501, _G501] ;
Ls = [_G775, _G775],
Ls0 = [_G787, _G775],
dif(_G775, _G787) .
Note the use of prolog-dif to declaratively state that two terms are different.
And by the way, "normal" cases work too:
?- no_consecutive_duplicates([a,b,c], Ls).
Ls = [a,b,c].
?- no_consecutive_duplicates([a,a,b,c,c], Ls).
Ls = [a,b,c].
Note that both queries succeed deterministically.
And isn't it nice that we can generalize this and inspect also slightly more complex cases?
?- no_consecutive_duplicates([a,b,X], Ls).
Ls = [a, b],
X = b ;
Ls = [a, b, X],
dif(X, b).
Stay pure folks!