Reputation: 11
I have written the simple code to reverse a typical integer list:
reverse([], []).
reverse([X], [X]).
reverse([X|Y], A) :- reverse(Y, Z), append(Z, [X], A).
? reverse([1, 2, 3], X)
X = [3, 2, 1].
However, I am pretty lost, as I am new to prolog, how to reverse a list that has other sublists within it, such as:
? reverse([1, [2, 3], [1, [3, [2, 4, 5], 1], 2], 5], X).
X = [5, [2, [1, [5, 4, 2], 3], 1], [3, 2], 1].
etc. Any help is appreciated, thanks!
Upvotes: 1
Views: 864
Reputation: 74197
Without using any built-ins, you can do:
reverse_nested_list( Xs, Rs ) :-
reverse_nested_list( Xs, [], Rs )
.
reverse_nested_list( [] , Rs , Rs ) .
reverse_nested_list( [X|Xs] , Ts , Rs ) :-
is_list(X) ,
! ,
reverse_nested_list(X,[],T) ,
reverse_nested_list(Xs,[T|Ts],Rs)
.
reverse_nested_list( [X|Xs] , Ts , Rs ) :-
reverse_nested_list(Xs,[X|Ts],Rs)
.
%
% cursory check for list-ness.
%
is_list(X) :- var(X), !, fail.
is_list([]).
is_list([_|_]).
Easy!
Upvotes: 1
Reputation: 60004
The definition can be made very compact:
deep_reverse(A, B) :- maplist(deep_reverse, A, R), !, reverse(R, B).
deep_reverse(A, A).
I've renamed it to be able to use the library predicate. Generally, I think it's best to avoid redefining library predicates.
Upvotes: 1
Reputation: 7209
This modification of your code works, but it's clumsy:
reverse([], []).
reverse([X|Y], A) :- reverse(Y, Z), reverse(X, Xrev), append(Z, [Xrev], A), !.
reverse(X, X). % not a list
BTW, reverse([X], [X]).
clause in your original code is not needed.
Update thanks to @mbratch comment:
reverse([X|Y], A) :- reverse(Y, Z), reverse(X, Xrev), append(Z, [Xrev], A).
reverse(X, X) :- X \= [_|_]. % X is not a list, or X is an empty list
Upvotes: 1