List Processing in Prolog
Backward Tail Recursion in Prolog / Forward Tail Recursion in Prolog
%%%%%%% lstdp.pro :: TP2.0 %%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% INCLUDE THIS FILE IF YOU WANT TO USE (ANY OF) THE FOLLOWING PREDICATES:
% 1.% lconcat (list,list,list), (i,i,o) % concatenate two lists
% 2.% lcount (list,real), (i,o), % count the list
% 3.% lsum (list,real), (i,o), % make sum
% 4.% singleton (list), (i), % is singleton?
% 5.% singleton (list,element), (i,i), % is singleton of ... ?
% 6.% lrev(list,list), (i,o), % reverse list
% 7.% plndrm(list), (i), % is palindrom?
% 8.% ismof(element,list), (i,i),(o,i), % is member of ?
% 9.% mknl(int,list), (i,o), % mknl(3,[1,2,3])
% 10. % mklel(int,list_of_empty_lists), (i,o), % mklel(3,[ [],[],[] ])
% 11. % mklxl(realx,int,llr), (i,i,o), % mklxl(0, 3, [ [0],[0],[0] ])
% 12. % maxlr(list,element), (i,o), % max element from a list
% 13. % minlr(list,element), (i,o), % min element from a list
% 14. % scalarp(lr,lr,real), (i,i,,o), % scalar product of two vectors
% 15. % sortins(inputlist,sortedlist), % Insertion sort
% 16. % addrealtolr(real,list,list), (i,i,o) % addrealtolr(3,[1,7,3],[4,10,6])
% 17. % lprod(list,result), (i,o) % lprod([6,3],18=6*3)
% 18. % pow(base,expo,result), (i,i,o) % pow(2,3,8)
% 19. % bitreversal(startindex, k, 1:N, Butterfly permutation)
% 20. % delfromlist(what, fromthislist) %
% 21. % ldeflate(list, set) % transform a list into a set
% 22. % rle(list, who, occ) % Run-Length Encoding
% 23. % rle(list, who, occ) % Run-Length Decoding
% WHERE: "list" could be a list of integers/reals/strings/chars/symbols,
% or a list of lists of integers/reals/strings/chars/symbols,
% according to the defined operation.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Nicolaie Popescu-Bodorin, 2009,
% http://fmi.spiruharet.ro/bodorin/
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DOMAINS
i=integer
r=real
s=string;
sym=symbol
c=char
li=i*
lli=li*
lr=r*
llr=lr*
lc=c*
llc=lc*
ls=s*
lls=ls*
lsym=sym*
llsym=lsym*
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Concatenate two lists (backward tail recursion):
PREDICATES
lconcat(lr,lr,lr)
lconcat(llr,llr,llr)
lconcat(lc,lc,lc)
lconcat(llc,llc,llc)
lconcat(ls,ls,ls)
lconcat(lls,lls,lls)
lconcat(lsym,lsym,lsym)
lconcat(llsym,llsym,llsym)
CLAUSES
% Concatenate two lists (backward tail recursion):
% lconcat(i,i,o)
lconcat([],L,L). % the most inner call;
lconcat([H|T],List,[H|TR]):-lconcat(T,List,TR).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Count the list (forward tail recursion):
PREDICATES
lcount(lr,r)
lcount(ls,r)
lcount(lc,r)
lcount(lsym,r)
lcount(llr,r)
lcount(lls,r)
lcount(llc,r)
lcount(lr,r,r)
lcount(ls,r,r)
lcount(lc,r,r)
lcount(lsym,r,r)
lcount(llr,r,r)
lcount(lls,r,r)
lcount(llc,r,r)
CLAUSES
% Count the list (forward tail recursion):
lcount(L,R):-lcount(L,0,R). % change arity in order to introduce the second parameter as Accumulator
lcount([],Ri,Ri):-!. % in the most inner call, the Accumulator is "copied as" (unified with) final result
lcount([_|T],Ri,R):-Ria=Ri+1,lcount(T,Ria,R). % while the input list is non empty, the Accumulator is updated and it is sent forward in the next call (forward tail recursive call)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Sum the elements of an array (forward tail recursion):
PREDICATES
lsum(lr,r)
lsum(lr, r,r)
CLAUSES
% Sum the elements of a list (forward tail recursion):
lsum([X],X):-!. %
lsum(L,R):-lsum(L,0,R). % change arity in order to introduce the second parameter as Accumulator
lsum([],Ri,Ri). % in the most inner call, the Accumulator is "copied as" (unified with) final result
lsum([H|T],Ri,R):-Ria=Ri+H,lsum(T,Ria,R). % while the input list is non empty, the Accumulator is updated and it is sent forward in the next call (forward tail recursive call)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Test if the input list is a singletone of the input element (bacward tail recursion)
PREDICATES
singleton(lr)
singleton(ls)
singleton(lc)
singleton(lsym)
singleton(li)
singleton(llr)
singleton(lls)
singleton(llc)
singleton(llsym)
singleton(lli)
singleton(lr,r)
singleton(ls,s)
singleton(lc,c)
singleton(lsym,sym)
singleton(li,i)
singleton(llr,lr)
singleton(lls,ls)
singleton(llc,lc)
singleton(llsym,lsym)
singleton(lli,li)
% USAGE:
% singleton(InputList,InputElement) :: Test if the input list is a singletone of the input element
% singleton(InputList,OutputElement) :: Test if the input list is a singletone of its head element. If YES, the output is the head of the list.
% singleton([_,_,_],X) :: will return Yes if X is Bounded.
% lcount(L,3), singleton(L,5) :: will return L=[5,5,5].
% singleton([_,X,_],Y) :: Unify X with Y if X id Bounded.
% finall(X,singleton([1,2,3],X),Y) :: will return Y=[];
CLAUSES
% Test if the input list is a singletone of the input element (bacward tail recursion):
singleton([H|T]):-singleton([H|T],H). % change arity in order to see if the head of the list equals all of its components
singleton([X],X):-!. % the most inner call;
singleton([R|T],R):-singleton(T,R). % if initial head equals current head, make the backward tail recursive call
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Reverse a list (forward tail recursion):
PREDICATES
lrev(lr,lr)
lrev(lc,lc)
lrev(ls,ls)
lrev(li,li)
lrev(lsym,lsym)
lrev(llr,llr)
lrev(llc,llc)
lrev(lls,lls)
lrev(lli,lli)
lrev(llsym,llsym)
lrev(lr,lr,lr)
lrev(lc,lc,lc)
lrev(ls,ls,ls)
lrev(li,li,li)
lrev(lsym,lsym,lsym)
lrev(llr,llr,llr)
lrev(llc,llc,llc)
lrev(lls,lls,lls)
lrev(lli,lli,lli)
lrev(llsym,llsym,llsym)
CLAUSES
% Reverse a list (forward tail recursion):
% lrev(i,o)
lrev(L,R):-lrev(L,[],R). % change arity in order to introduce the second parameter as Accumulator
lrev([],Ri,Ri). % in the most inner call, the Accumulator is "copied as" (unified with) final result
lrev([H|T],Ri,R):-lrev(T,[H|Ri],R). % forward tail recursive call
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Test if the input list is a palindrome:
PREDICATES
plndr(lr)
plndr(lc)
plndr(ls)
plndr(li)
plndr(lsym)
plndr(llr)
plndr(llc)
plndr(lls)
plndr(lli)
plndr(llsym)
CLAUSES
% Test if the input list is a palindrome:
plndr(L):-lrev(L,L).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Test if the input element is memeber of the input list (forward tail recursion):
PREDICATES
ismof(r,lr)
ismof(c,lc)
ismof(s,ls)
ismof(i,li)
ismof(sym,lsym)
ismof(lr,llr)
ismof(lc,llc)
ismof(ls,lls)
ismof(li,lli)
ismof(lsym,llsym)
ismof(r,lr,r,r)
ismof(c,lc,r,r)
ismof(s,ls,r,r)
ismof(i,li,r,r)
ismof(sym,lsym,r,r)
ismof(lr,llr,r,r)
ismof(lc,llc,r,r)
ismof(ls,lls,r,r)
ismof(li,lli,r,r)
ismof(lsym,llsym,r,r)
% USAGE:
% ismof(InputElement,InputList) :: test if the input element is memeber of the input list
% lcount(L,4),ismof(10,L) :: will return L=[10,10,10,10];
CLAUSES
% Test if the input element is memeber of the input list (forward tail recursion):
% (i,i),(o,i)!
ismof(E,L):-ismof(E,L,0,C),C>0. % change arity in order to introduce the third parameter as Accumulator for the forth parameter which is the number of occurences of the given element in the given list
ismof(_,[],Ri,Ri). % in the most inner call, the Accumulator (third parameter) is "copied as" (unified with) final result for the number of occurences
ismof(E,[E|T],Ci,C):-Cia=Ci+1,ismof(E,T,Cia,C),!. % if the given element equals the head of the current list, count the occurence and make the forward recursive call on the tail
ismof(E,[_|T],Ci,C):-ismof(E,T,Ci,C). % or else, make the recursive call without updating the Accumulator
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% mknl(N,R) :: Expand a list (R) of consecutive integers starting from 1, ending with the given number N (forward tail recursion):
PREDICATES
mknl(r,lr) % (i,o)
mknl(r,lr,lr) % (i,a,o)
% USAGE:
% mknl(input, output)
% mknl(5,L) :: will return L=[1,2,3,4,5];
CLAUSES
% mknl(N,R) :: Expand a list (R) of consecutive integers starting from 1, ending with the given number N (forward tail recursion):
mknl(N,R):-N>0,mknl(N,[],R). % change arity in order to introduce the second parameter as Accumulator
mknl(0,Ri,Ri). % in the most inner call, the Accumulator (second parameter) is "copied as" (unified with) final result
mknl(Ni,Ri,R):-Ni>0,Nia=Ni-1,mknl(Nia,[Ni|Ri],R). % forward tail recursive call
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% mklel(N,L) :: Expand a list (L) containing N empty lists (forward tail recursion):
PREDICATES
mklel(i,llr)
mklel(i,lli)
mklel(i,lls)
mklel(i,llc)
mklel(i,llsym)
mklel(i,llr,llr)
mklel(i,lli,lli)
mklel(i,lls,lls)
mklel(i,llc,llc)
mklel(i,llsym,llsym)
% USAGE:
% mklel(4,R) :: will return R=[ [],[],[],[] ]
CLAUSES
% mklel(N,L) :: Expand a list (L) containing N empty lists (forward tail recursion):
mklel(N,LR):-mklel(N,[],LR). % change arity in order to introduce the second parameter as Accumulator
mklel(0,Ri,Ri). % in the most inner call, the Accumulator (second parameter) is "copied as" (unified with) final result
mklel(N,Ri,R):-N>0, Na=N-1, mklel(Na, [ []|Ri ], R). % forward tail recursive call
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% mklxl(R,N,L) :: Expand a list (L) containing N lists [R] (forward tail recursion):
PREDICATES
mklxl(r,i,llr)
mklxl(r,i,llr,llr)
% USAGE:
% mklxl(0.5, 4, L) :: will return L=[ [0.5],[0.5],[0.5],[0.5] ]
CLAUSES
% mklxl(R,N,L) :: Expand a list (L) containing N lists [R] (forward tail recursion):
mklxl(X,N,LR):-mklxl(X,N,[],LR). % change arity in order to introduce the third parameter as Accumulator
mklxl(_,0,Ri,Ri). % in the most inner call, the Accumulator (third parameter) is "copied as" (unified with) final result
mklxl(X,N,Ri,R):-N>0, Na=N-1, mklxl(X, Na, [ [X]|Ri ], R). % forward tail recursive call
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
PREDICATES
maxlr(lr,r)
maxlr(lr,r,r)
minlr(lr,r)
minlr(lr,r,r)
% USAGE:
% maxim/minim of a numeric list
CLAUSES
maxlr([X],X):-!.
maxlr([H|T],R):-maxlr(T,H,R).
maxlr([],Ri,Ri). % (i,i -> o)
maxlr([H|T],Ri,R):-
Ri>=H, maxlr(T,Ri,R);
Ri o)
minlr([H|T],Ri,R):-
Ri<=H, minlr(T,Ri,R);
Ri>H, minlr(T,H,R).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Compute scalar product of two vectors:
PREDICATES
scalarp(lr,lr,r)
scalarp(lr,lr,r,r)
CLAUSES
% Compute scalar product of two vectors (forward tail recursion):
scalarp(L,V,R):-lcount(L,N),lcount(V,N),scalarp(L,V,0,R). % test if the lists are equal in length and change arity in order to introduce an Accumulator (third parameter)
scalarp([],[],Ri,Ri). % in the most inner call, the Accumulator (third parameter) is "copied as" (unified with) final result
scalarp([H1|T1],[H2|T2],Ri,R):-Ria=Ri+H1*H2, scalarp(T1,T2,Ria,R). % forward tail recursive call
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% INSERTION SORT:
PREDICATES
sortins(lr,lr)
insinord(lr,lr,lr)
insertr(r,lr,lr)
%test(lr,lr,lr,r)
% INSERTION SORT:
CLAUSES
% 1
sortins([],[]):-!.
sortins([H|T],R):-insinord(T,[H],R),!.
insinord([],Ri,Ri).
insinord([H|T],Ri,R):-insertreal(H,Ri,Ria),insinord(T,Ria,R).
insertreal(X,[H],[H,X]):-H<=X,!.
insertreal(X,[H|T],[X,H|T]):-X<=H,!.
insertreal(W,[X,Y|T],[X,W,Y|T]):-X<=W,W<=Y,!.
insertreal(W,[X,Y|T],[X|R]):-insertreal(W,[Y|T],R),!.
% 2
%sortins([],[]):-!.
%sortins([H|T],R):-insinord(T,[H],R),!.
%insinord([],Ri,Ri).
%insinord([H|T],Ri,R):-insertreal(H,Ri,Ria),insinord(T,Ria,R).
%insertreal(X,[H],[H,X]):-H<=X,!.
%insertreal(X,[H|T],[X,H|T]):-X<=H,!.
%insertreal(X,L,R):- test(A,B,L,X),lconcat(A,[X|B],R).
%test(A,B,L,X):-lconcat(A,B,L),maxlr(A,AM),minlr(B,Bm),AM<=X,X<=Bm.
% 3
%sortins([],[]):-!.
%sortins([H|T],R):-insinord(T,[H],R),!.
%insinord([],Ri,Ri).
%insinord([X],[H],[H,X]):-H<=X,!.
%insinord([X],[H|T],[X,H|T]):-X<=H,!.
%insinord([W],[X,Y|T],[X,W,Y|T]):-X<=W,W<=Y,!.
%insinord([W],[X,Y|T],[X|R]):-insinord([W],[Y|T],R),!.
%insinord([H|T],Ri,R):-insinord([H],Ri,Ria),insinord(T,Ria,R).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Additive shifting of all components within a given list (forward tail recursion):
PREDICATES
addrealtolr(r,lr,lr) % (i,i,o)
addrealtolr(r,lr,lr,lr) % (i,i,a,o)
% USAGE:
% additive shifting of all components within a given list
% addrealtolr(0.5,[1,4,2],L) :: will return L=[ 1.5, 4.5, 2.5]
CLAUSES
% Additive shifting of all components within a given list (forward tail recursion):
addrealtolr(N,L,R):-addrealtolr(N,L,[],R). % change arity in order to introduce an Accumulator (third parameter)
addrealtolr(_,[],Ri,R):-lrev(Ri,R). % in the most inner call, the Accumulator (third parameter) is reversed and unified with final result
addrealtolr(N,[H|T],Ri,R):-Ha=H+N, addrealtolr(N,T,[Ha|Ri],R). % forward tail recursive call
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Compute the product of all components of a numeric list (forward tail recursion)
PREDICATES
lprod(lr,r)
lprod(lr, r,r)
% USAGE
% lprod([1,2,3],R) :: will return R=1*2*3=3!=6
CLAUSES
Compute the product of all components of a numeric list (forward tail recursion)
lprod([X],X):-!.
lprod(L,R):-lprod(L,1,R). % change arity in order to introduce an Accumulator (second parameter)
lprod([],Ri,Ri). % in the most inner call, the Accumulator is unified with final result
lprod([H|T],Ri,R):-Ria=Ri*H,lprod(T,Ria,R). % while the current list is not empty, update the Accumulator and make forward tail recursive call
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Compute positive integer power of a real number (forward tail recursion):
PREDICATES
pow(r,r,r)
% USAGE
% pow(1.6,2,R) :: will return R=2.56
CLAUSES
% Compute positive integer power of a real number (forward tail recursion using a list)
pow(B,E,R):-lcount(L,E),singleton(L,B),lprod(L,R).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Compute Butterfly Permutation (forward tail recursion)
% http://fmi.spiruharet.ro/bodorin/articles/brdfpvdro.pdf (Butterfly Permutation, Fourier Permutation, Bit Reversal)
PREDICATES
% bitreversal(0,3,[0,1,2,3,4,5,6,7],[0,4,2,6,1,5,3,6])
% bitreversal(S,K,I,BR)
bitreversal(r,r,lr,lr) % (i,i,o,o)
% bitrev(0,3,[0,4,2,6,1,5,3,6])
% bitrev(S,K,BR)
bitrev(r,r,lr,lr) % (i,i,ia -> o)
CLAUSES
% Compute Butterfly Permutation
bitreversal(S,K,I,BR):-pow(2,K,N), mknl(N,I1), addrealtolr(-1,I1,I0), addrealtolr(S,I0,I), bitrev(S,K,[S],BR).
bitrev(_,1,Ri,R):-addrealtolr(1,Ri,Ri2),lconcat(Ri,Ri2,R).
bitrev(S,K,Ri,R):- Ka=K-1, pow(2,Ka,P), addrealtolr(P,Ri,Ri2), lconcat(Ri,Ri2,Ria), bitrev(S,Ka,Ria,R).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Delete an element from a list (forward tail recursion)
PREDICATES
delfromlist(r,lr,lr)
delfromlist(i,li,li)
delfromlist(c,lc,lc)
delfromlist(s,ls,ls)
delfromlist(sym,lsym,lsym)
delfromlist(lr,llr,llr)
delfromlist(li,lli,lli)
delfromlist(lc,llc,llc)
delfromlist(ls,lls,lls)
delfromlist(lsym,llsym,llsym)
delfromlist(r,lr,lr,lr)
delfromlist(i,li,li,li)
delfromlist(c,lc,lc,lc)
delfromlist(s,ls,ls,ls)
delfromlist(sym,lsym,lsym,lsym)
delfromlist(lr,llr,llr,llr)
delfromlist(li,lli,lli,lli)
delfromlist(lc,llc,llc,llc)
delfromlist(ls,lls,lls,lls)
delfromlist(lsym,llsym,llsym,llsym)
% USAGE:
% delfromlist(1,[1,2,1,3,1,4,1,5],R) :: will return R=[2,3,4,5]
CLAUSES
% Delete an element from a list (forward tail recursion)
delfromlist(E,L,R):-delfromlist(E,L,[],R). % change arity in order to introduce an Accumulator (third parameter)
delfromlist(_,[],Ri,R):-lrev(Ri,R). % in the most inner call, the Accumulator (third parameter) is reversed and unified with final result
delfromlist(E,[E|T],Ri,R):-delfromlist(E,T,Ri,R),!. % if E is the head of the list, make recursive call on the tail without updating the Accumulator
delfromlist(E,[H|T],Ri,R):-delfromlist(E,T,[H|Ri],R). % or else (see the previous cut), update the Accumulator and make the recursive call
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Eliminate all duplicates from a given list (forward tail recursion)
PREDICATES
ldeflate(lr,lr)
ldeflate(li,li)
ldeflate(lc,lc)
ldeflate(ls,ls)
ldeflate(lsym,lsym)
ldeflate(llr,llr)
ldeflate(lli,lli)
ldeflate(llc,llc)
ldeflate(lls,lls)
ldeflate(llsym,llsym)
ldeflate(lr,lr,lr)
ldeflate(li,li,li)
ldeflate(lc,lc,lc)
ldeflate(ls,ls,ls)
ldeflate(lsym,lsym,lsym)
ldeflate(llr,llr,llr)
ldeflate(lli,lli,lli)
ldeflate(llc,llc,llc)
ldeflate(lls,lls,lls)
ldeflate(llsym,llsym,llsym)
% USAGE:
ldeflate([4,1,2,1,4,5], L) :: will return L=[4,1,2,5]
% Eliminate all duplicates from a given list (forward tail recursion)
CLAUSES
ldeflate(L,R):-ldeflate(L,[],R). % change arity in order to introduce an Accumulator (second parameter)
ldeflate([],Ri,R):-lrev(Ri,R). % in the most inner call, the Accumulator is reversed and unified with final result
ldeflate([H|T],Ri,R):-delfromlist(H,T,Ta), ldeflate(Ta,[H|Ri],R). % forward tail recursive call
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Compute the Run-Length Encoding of a list
PREDICATES
rle(lr, lr,lr) % (i,o,o)
rle(lr,lr,lr,lr,lr) % (i,ri,ri,r,r)
rld(lr,lr ,lr) % (i,i,o)
rld(lr,lr,lr,lr) % (i,i,ri,r)
mkctl(r,r,lr)
mkctl(r,r,lr,lr)
CLAUSES
% Run-Length Encoding
rle([H|T],W,O):-
rle(T,[H],[1],Wrv,Orv), % change arity in order to introduce two Accumulators (second and third parameters)
lrev(Wrv,W),lrev(Orv,O).
%nl,write("Who:"),write(W),
%nl,write("Occ:"),write(O),
%nl.
rle([],RWi,ROi,RWi,ROi). % ( i,(i,i)->(o,o) ) % in the most inner call, the Accumulators are unified with final result results
rle([H|T],[H|T2],[Oi|T3],W,O):-
Oia=Oi+1,
rle(T,[H|T2],[Oia|T3],W,O),!. % encode reduntance and make the recursive call
rle([H|T],[X|T2],Oi,W,O):-
lconcat([H],[X|T2],Wia),
lconcat([1],Oi,Oia),
rle(T,Wia,Oia,W,O). % forward tail recursive call
% Compute the Run-Length Encoding of a list:
rld(W,O,R):-rld(W,O,[],R). % change arity in order to introduce an Accumulators (third parameter)
rld([],[],Ri,Ri). % (i,i,i->o) % in the most inner call, the Accumulators are unified with final result results
rld([W|WT],[O|OT],Ri,R):-
mkctl(W,O,URi),lconcat(Ri,URi,Ria),
rld(WT,OT,Ria,R). % forward tail recursive call
% mkctl(Who,Occ,[3,3,3,3,3]) Expand a singletone containing Occ occurences of Who (forward tail recursion)
% USAGE: mkctl(3,5,[3,3,3,3,3])
mkctl(W,O,R):-mkctl(W,O,[],R).
mkctl(_,0,Ri,Ri):-!. % (i,i,i->o)
mkctl(W,O,Ri,R):-
Oa=O-1,
mkctl(W,Oa,[W|Ri],R).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%