Here is one solution:
split([],[]).
split([Head|Tail],[[Head]|Split]) :-
split(Tail,Split).
split([Head|Tail],[[Head|List]|Split]) :-
split(Tail,[List|Split]).
For example:
?- split([1,2,3,4],Lists), split(Recover,Lists).
Lists = [[1], [2], [3], [4]],
Recover = [1, 2, 3, 4] ;
Lists = [[1], [2], [3, 4]],
Recover = [1, 2, 3, 4] ;
Lists = [[1], [2, 3], [4]],
Recover = [1, 2, 3, 4] ;
Lists = [[1], [2, 3, 4]],
Recover = [1, 2, 3, 4] ;
Lists = [[1, 2], [3], [4]],
Recover = [1, 2, 3, 4] ;
Lists = [[1, 2], [3, 4]],
Recover = [1, 2, 3, 4] ;
Lists = [[1, 2, 3], [4]],
Recover = [1, 2, 3, 4] ;
Lists = [[1, 2, 3, 4]],
Recover = [1, 2, 3, 4] ;
false.
This solution is based on the following observation. I will refer to the flattened list as the input list and the unflattened list as the output list. In the recursive case, the input list has the form [H|T]
and split(T,R)
succeeds by assumption. There are three cases to consider.
- If
R = []
we can begin constructing a new list whose last element is H
.
- If
R = [_|_]
we can begin constructing a new list whose last element is H
.
- If
R = [L|_]
we can continue constructing L
by prepending H
to L
.
In each case, we obtain valid output lists. The first two cases are implemented by the second clause of split/2
(it doesn't matter whether R = []
or R = [_|_]
) and the third by the third clause.