Here are some ideas to get you started.
You're going to need to keep a running count of repeated elements since your results have counters. So right off, consider an auxiliary predicate that includes the counter, which is a typical way of handling it in Prolog. This use of a counter is commonly referred to as an accumulator.
compress(L, C) :-
compress(L, 1, C). % Start counter at 1
Now you'll need to consider a few different cases:
compress([], _, []). % This is an easy one!
This says that if I compress an empty list, I get an empty list.
compress([H], Count, [[H,Count]]). % This is an easy one!
This one says if I compress a list of one element and my current running count is Count
, then the result is [[H, Count]]
.
compress([H, H|T], Count, TC) :-
...
This is the case where I have a running count and the element is still repeating. The result is going to be a list TC
but I don't know what it looks like yet since we're still in a repeating cycle and it will need to be determined through recursion. What should this predicate look like? In your example, you included a count in the result when the first two elements were the same, which is not the right time to include the count (see the clause below).
compress([H1, H2|T], Count, [[H1,Count]|TC]) :-
dif(H1, H2),
...
This is the case where I have a running count and the repeating stops at H1
. Since the repeating of the current cycle ends with H1
, we know the result looks like [[H1, Count]|TC]
because H1
has repeated Count
times. We just have yet to determine the rest of the list TC
through recursion. What should this predicate implementation look like?
There are other ways of doing the above logic (e.g., with ->
and ;
construct, etc), but this will keep it simple.
Try to think of these as rules where the head of the predicate clause is the assertion which will be true if the following elements of the clause are true. And think recursively.
As an afterthought, this could be done without a separate accumulator by using the result to carry the accumulator:
compress([], []).
compress([H], [[H,1]]).
compress([H1,H2|T], [[H1,1]|R]) :-
dif(H1, H2),
compress(...). % left as an exercise
compress([H,H|T], [[H,N]|R]) :-
N #= N1 + 1,
compress(...). % left as an exercise