Reputation: 368
My problem is, that I want to make a rule for splitting a list to several lists, containing only 3 items from the original, in order.
For example:
/*original list:*/
Fruits=[apple,banana,orange,pear, lemon, melon]
?-Split(Fruits).
/*results:*/
[apple,banana,orange];
[banana,orange,pear];
[orange,pear,lemon];
[pear,lemon,melon].
Is there any way to do this? :S
Upvotes: 3
Views: 2773
Reputation:
Prolog is excellent for this task. Just observe that append/3 can be used in various directions:
% append(+List,+List,-List)
% append(-List,-List,+List)
append([], X, X).
append([X|Y], Z, [X|T]) :-
append(Y, Z, T).
Now simply define split/2 as follows. It will find _1 and _2 such that L = _1 ++ S ++ _2, where ++ is the list concatenation:
% split(+List,-Sublist)
split(L, S) :-
append(_, H, L),
append(S, _, H).
And here you go with your problem:
?- Fruits=[apple,banana,orange,pear,lemon,melon], Split=[_,_,_], split(Fruits,Split).
Fruits = [apple,banana,orange,pear,lemon,melon],
Split = [apple,banana,orange] ;
Fruits = [apple,banana,orange,pear,lemon,melon],
Split = [banana,orange,pear] ;
Fruits = [apple,banana,orange,pear,lemon,melon],
Split = [orange,pear,lemon] ;
Fruits = [apple,banana,orange,pear,lemon,melon],
Split = [pear,lemon,melon] ;
No
Bye
Best Regards
Upvotes: 3
Reputation: 7493
You can refer to this excellent answer @false provided some times ago.
Quickly adapting his solution, you could write:
seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).
split_3(List, Result) :-
length(Result, 3),
phrase((seq(_),seq(Result),seq(_)),List).
Note that you could achieve the same thing with append/2
(or append/3
with one more call):
split_3(List, Result) :-
length(Result, 3),
append([_, Result, _], List).
But append/2
is not really intended for such manipulations. DCG use difference lists, which are more efficient.
Upvotes: 3