In this answer, we use clpfd constraints for expressing declarative integer arithmetic.
:- use_module(library(clpfd)).
We define split/4
by combining the code of append/3
and the code1 of fd_length/2
.
Note the parallels of fd_length/2
with split/4
and of fd_length/3
with split_/5
:
split(Zs, N, Xs, Ys) :- %% fd_length(Xs, N) :-
N #>= 0, %% N #>= 0,
split_(Xs, N,0, Ys, Zs). %% fd_length(Xs, N,0).
%%
split_([], N,N0, Zs, Zs) :- %% fd_length([], N,N0) :-
N #= N0. %% N #= N0.
split_([X|Xs], N,N0, Ys, [X|Zs]) :- %% fd_length([_|Xs], N,N0) :-
N1 #= N0+1, %% N1 #= N0+1,
N #>= N1, %% N #>= N1,
split_(Xs, N,N1, Ys, Zs). %% fd_length(Xs, N,N1).
Now, if look at the code of split_/5
again, then we can see the code of append/3
in it:
%% split_([], N,N0, Zs, Zs) :- %% append([], Zs, Zs).
%% N #= N0, %%
%% split_([X|Xs], N,N0, Ys, [X|Zs]) :- %% append([X|Xs], Ys, [X|Zs]) :-
%% N1 #= N0+1, %%
%% N #>= N1, %%
%% split_(Xs, N,N1, Ys, Zs). %% append(Xs, Ys, Zs).
Sample queries:
?- N = 2, split(XsYs, N, Xs, Ys).
XsYs = [_A,_B|Ys], N = 2, Xs = [_A,_B]
; false.
?- N = 2, XsYs = [a,b,c,d,e], split(XsYs, N, Xs, Ys).
XsYs = [a,b,c,d,e], N = 2, Xs = [a,b], Ys = [c,d,e]
; false.
?- XsYs = [a,s,d,f,g,h,j], split(XsYs, N, Xs, Ys).
XsYs = [a,s,d,f,g,h,j], N = 0, Xs = [] , Ys = [a,s,d,f,g,h,j]
; XsYs = [a,s,d,f,g,h,j], N = 1, Xs = [a] , Ys = [s,d,f,g,h,j]
; XsYs = [a,s,d,f,g,h,j], N = 2, Xs = [a,s] , Ys = [d,f,g,h,j]
; XsYs = [a,s,d,f,g,h,j], N = 3, Xs = [a,s,d] , Ys = [f,g,h,j]
; XsYs = [a,s,d,f,g,h,j], N = 4, Xs = [a,s,d,f] , Ys = [g,h,j]
; XsYs = [a,s,d,f,g,h,j], N = 5, Xs = [a,s,d,f,g] , Ys = [h,j]
; XsYs = [a,s,d,f,g,h,j], N = 6, Xs = [a,s,d,f,g,h] , Ys = [j]
; XsYs = [a,s,d,f,g,h,j], N = 7, Xs = [a,s,d,f,g,h,j], Ys = []
; false.
?- Xs = [a,b,c], Ys = [d,e,f], split(XsYs, N, Xs, Ys).
XsYs = [a,b,c,d,e,f], N = 3, Xs = [a,b,c], Ys = [d,e,f].
Footnote 1: To accentuate the parallels, the program text of fd_length/2
(optimized variant) was altered slightly:
L
was replaced by Xs
,
the argument pair N, N0
by N,N0
, and
(is)/2
by (#=)/2
.