4
votes

I'm new in prolog and I'm trying to write the predicate encode(L,L1) which counts the duplicates of elements in L ,for example:

encode([4,4,4,3,3],L).

L=[3,4,2,3].

This is what I have written:

encode(L,L1) :- encode(L,1,L1).

encode([],_,[]).      
encode([H],N,[N,H]).      
encode([H,H|T],N1,[N,H|T1]) :- M is N1+1, encode([H|T],M,[N,H|T1]).     
encode([H,Y|T],N,[N,H|T1]) :- H\=Y, encode([Y|T],T1).   

The above predicate is not reversible. It only works if the first parameter is provided.

How can I write encode reversible?
For example:

encode(L,[3,4,2,3]).           
L = [4,4,4,3,3].
1
In place of M is N1+1 try M #= N1 + 1. Make sure you load the CLP(FD) module (:- use_module(library(clpfd)).) And in place of \= use \==.lurker
@lurker ,I tried the above but still after making the changes ,the problem remains : encode(L,[3,4,2,3]) does not give any answer (it throws exception "Out of local stack" ).coder

1 Answers

4
votes

I think your algorithm has a redundant counter in it. A little simplified would be:

encoded([], []).
encoded([X], [1,X]).
encoded([X,Y|T], [1,X|R]) :-
    dif(X, Y),
    encoded([Y|T], R).
encoded([X,X|T], [N,X|R]) :-
    N #> 1,
    N #= N1 + 1,
    encoded([X|T], [N1,X|R]).

Note in the last clause we need to ensure that N is greater than 1 as well.