0

trying to write code that splits a list in half for even numbers of elements, eg. split([1,2,3,4],A,B) would give A = [1,2] and B = [3,4].

And behave like Java list.length()/2 would for odd numbers of elements, so split([1,2,3,4,5],A,B) would give A = [1,2] and B = [3,4,5].

The closest I can get is something like this, but this isn't quite right, and only works for even numbers.

split(L, A, B) :-
  append(A, B, L),
  length(A, N),
  length(B, N).
lurker
  • 56,987
  • 9
  • 69
  • 103
AL_
  • 1
  • 1

1 Answers1

2

One way to split a list in half in Prolog is to do so using append/3 and the same_length/2 predicates:

split(List, Left, Right) :-
    same_length(Left, Right),
    append(Left, Right, List).
split(List, Left, [R|Rs]) :-
    same_length(Left, Rs),
    append(Left, [R|Rs], List).

This gives you:

| ?- split(L, A, B).
A = B, B = L, L = [] ;
A = [_1038],
B = [_1048],
L = [_1038, _1048] ;
A = [_1038, _1044],
B = [_1054, _1060],
L = [_1038, _1044, _1054, _1060] ;
A = [_1038, _1044, _1050],
B = [_1060, _1066, _1072],
L = [_1038, _1044, _1050, _1060, _1066, _1072] ;
...
false
  • 10,264
  • 13
  • 101
  • 209
lurker
  • 56,987
  • 9
  • 69
  • 103
  • Your definition could have better termination properties. Currenty: `split(A,B,C) terminates_if b(A);b(B)` What about `b(C)`? – false Dec 07 '17 at 21:21
  • @false ah good catch. Definitely an issue with `split(L, A, []).`. I'll think on that one. – lurker Dec 07 '17 at 21:40
  • 1
    Now the first argument does not influence termination. Where is the progress? (A pity that this is now a dupe...) – false Dec 08 '17 at 19:24
  • Btw, which toplevel do you use? Sometimes its the _2343243 ugly SWI, and sometimes you have the regular variable names `A, B, C...`. – false Dec 08 '17 at 19:32
  • @false yeah I was probably hasty with this solution as well. For top level, I usually default to GNU Prolog. I sometimes go to SWI for specific features it provides. In the above, I had access to neither when I ran the code and used SWISH (SWI based). I had to kind of "fake" the semicolon responses since SWISH uses button clicks for "next". – lurker Dec 08 '17 at 23:51
  • Just realize that GNU gives for `length(L,2), L = K` the answer `L = [A,B], K = [A,B]``. I always thought it would give `L = [_A,_B]` as SICStus does. That's why. – false Dec 09 '17 at 14:58