3

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

false
  • 10,264
  • 13
  • 101
  • 209
Peter Ivanics
  • 518
  • 8
  • 13

2 Answers2

3

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.

Community
  • 1
  • 1
m09
  • 7,490
  • 3
  • 31
  • 58
  • 1
    If you're interested in Prolog, taking the time to understand correctly what's going on in the answer I linked is time well spent btw! – m09 Apr 06 '12 at 10:07
3

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