Вот одно решение:
split([],[]).
split([Head|Tail],[[Head]|Split]) :-
split(Tail,Split).
split([Head|Tail],[[Head|List]|Split]) :-
split(Tail,[List|Split]).
Например:
?- 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.
Это решение основано на следующем наблюдении. Я буду ссылаться на сплющенный список как список ввода , а нераспечатанный список - как список вывода . В рекурсивном случае входной список имеет форму [H|T]
, а split(T,R)
выполняется по предположению. Необходимо рассмотреть три случая.
- Если
R = []
, мы можем начать создавать новый список, последний элемент которого H
. - Если
R = [_|_]
, мы можем начать создавать новый список, последний элемент которого H
. - Если
R = [L|_]
, мы можем продолжить построение L
, добавив от H
к L
.
В каждом случае мы получаем действительные списки вывода. Первые два случая реализуются вторым предложением split/2
(неважно, R = []
или R = [_|_]
), а третье - третьим.