:- module(_,_,[]).

% Lists - two versions of reverse

% reverse_naive(X,Y): Y is list X reversed

% First version - from definition
% Given a list [H|T] the reversed version has H at the 
% end of the list that is the result of reversing T

reverse_naive([],[]).
reverse_naive([X|Xs],Ys) :- 
    reverse_naive(Xs,Zs),
    list_append(Zs,[X],Ys).
% Try:
% ?- reverse_naive([a,b,c],X).
% ?- reverse_naive(X,[c,b,a]).
% ?- reverse_naive(X,Y).


% Second version, using accumulating parameter:

reverse_acc(Xs,Ys) :- 
    reverse_(Xs,[],Ys).

reverse_([],Ys,Ys).
reverse_([X|Xs],Acc,Ys) :-
    NewAcc=[X|Acc],
    reverse_(Xs,NewAcc,Ys).

% ?- reverse_acc([a,b,c],X).
% ?- reverse_acc(X,[c,b,a]).
% ?- reverse_acc(X,Y).

% Auxiliary predicates: 

% append(X,Y,Z): list Z is X and Y concatenated
list_append([],L,L) :- 
    list(L).
list_append([X|Xs],Ys,[X|Zs]) :- 
    list_append(Xs,Ys,Zs).

list([]).
list([_|Y]) :-
     list(Y).
