prolog

Prolog: Compress a list that contains segments of continuous numbers to a list which contains list of range of segments [start,end]


I'm new in prolog and I'm trying to solve this exercise but I can not get my desired output.Compressing a list of integers to a compressed list. List contains segments of continuous integers.A segment with length greater than 2 will be encoded to list [start, end], end is inclusive. If the length is not greater than 2 will be kept no change.

Sample:

compress([3,4,6,7,8,9,10,15,16,17,20,22,23,24,25], CompressedList).

CompressedList = [3, 4, [6,10],[15, 17],20, [22,25]].

My incorrect output:

CompressedList = [[3, [4]], [6,[10]],[15, [17]],20, [22,[25]]].

My code is:

compress([], []).

compress([X], [X]).

compress([X, Y | T], [X | CompressedTail]) :-
    X + 1 =\= Y,
    compress([Y | T], CompressedTail).
    
    
compress([X, Y | T], [[X, YLast] | CompressedTail]) :-
    compress_consecutive([Y | T], YLast, Next),
    compress(Next, CompressedTail).


compress_consecutive([], Last, []) :- Last = [].
compress_consecutive([X], [X], []) :- !.
compress_consecutive([X, Y | T], Last, Next) :-
    X + 1 =:= Y,
    compress_consecutive([Y | T], Last, Next).
    
    
compress_consecutive([X, Y | T], [X], [Y | T]) :- X + 1 =\= Y. ```

Solution

  • %compress/2 predicate
    % Base case
    compress([], []).
    
    % Base case
    compress([X], [X]).
    
    compress([X, Y | T], [X | CompressedTail]) :-
        X + 1 =\= Y,
        compress([Y | T], CompressedTail).
        
    compress([X, Y, Z| T], [X, Y| CompressedTail]) :-
        X + 1 =:= Y,
        Y + 1 =\= Z,
        compress([Z | T], CompressedTail).
        
        
    compress([X, Y | T], [[X, YLast] | CompressedTail]) :-
        compress_consecutive([Y | T], YLast, Next),
        compress(Next, CompressedTail).
    
    % Helper predicate to find the last element of a consecutive segment.
    compress_consecutive([], Last, []) :- Last = [].
    compress_consecutive([X], X, []) :- !.
    compress_consecutive([X, Y | T], Last, Next) :-
        X + 1 =:= Y,
        compress_consecutive([Y | T], Last, Next).
        
        
    compress_consecutive([X, Y | T], X, [Y | T]) :- 
    X + 1 =\= Y.