2015-08-24 94 views
2

我在幾周的時間裏開始使用prolog,但是我更深入地看到構建操作列表的遞歸謂詞。我的問題是:有可能構建一個預測,在給定數量的其他列表中拆分給定列表?在Prolog中動態分割列表

例如,我想象:

split([H|T], NumberLists, Lists) - 遞歸實現 -

?- split([1,2,3,4,5,6,7,8],2,Lists). 
Lists = [[1,2,3,4],[5,6,7,8]]. 

?- split([1,2,3,4,5,6,7,8],4,Lists). 
Lists = [[1,2],[3,4],[5,6],[7,8]]. 

有人可以給我實現的一個例子嗎?

謝謝!

+1

**有人可以給我一個實現的例子嗎?**不,你給我們你試過的,我們會幫你的! – joel76

+0

不要自己編寫遞歸代碼,而應考慮使用buitin /庫謂詞的組合。 – repeat

+0

@repeat提示:'split(L,N,S): - length(S,N),append(S,L).' – CapelliC

回答

1

這樣的事情應該做的。沒有內置謂詞:

partition([] , _ , []  ) . % the empty list is already partitioned 
partition(Xs , N , [Pfx|Ys]) :- % for a non-empty list, we... 
    take(N,Xs, Pfx , Sfx) ,  % - split it into a prefix of (at most) length N and its suffix. 
    partition(Sfx,N,Ys)    % - recursively partition the suffix 
    .        % Easy! 

take(0 , Xs , []  , Xs ) .  % if we reach zero, we're done. Close the prefix and hand back whatever is left over. 
take(N , [] , []  , [] ) :- % if we exhaust the source list, we're done. close the prefix and hand back the empty list as the suffix. 
    N > 0        % - assuming, of course, that N is greater than zero. 
    .         % 
take(N , [X|Xs] , [X|Ys] , Sfx) :- % otherwise prepend the current item to the prefix 
    N > 0 ,       % - assuming N is greater than zero, 
    N1 is N-1 ,      % - then decrement N 
    take(N1,Xs,Ys,Sfx)     % - and recurse down. 
    .         % Also easy! 
1

如何使用

:- use_module(library(clpfd)). 
:- use_module(library(lambda)). 

我們定義split/3這樣的:

split(Xs,N,Yss) :- 
    length(Xs,L), 
    N #=< L, 
    [L0,L1] ins 1..sup, 
    L0 #= L/N, 
    L1 #= L - L0*(N-1), 

    % enumerate `N` *now* if domain is finite. 
    % ideally, length/2 does something like this (by itself). 
    (fd_size(N,Size),integer(Size) -> indomain(N) ; true), 

    length(Yss,N), 
    append(Yss0,[Ys],Yss),   % creates useless choicepoint 
    maplist(\Ls^length(Ls,L0),Yss0), 
    length(Ys,L1), 
    append(Yss,Xs).     % note we use append/2 here, not append/3 

首先,查詢OP了:

?- split([1,2,3,4,5,6,7,8],2,Lists). 
    Lists = [[1,2,3,4], [5,6,7,8]] 
; false. 

?- split([1,2,3,4,5,6,7,8],4,Lists). 
    Lists = [[1,2], [3,4], [5,6], [7,8]] 
; false. 

然後,一個更普遍的例子:

?- split([1,2,3,4,5,6,7,8],N,Lss). 
    N = 1, Lss = [[1,2,3,4,5,6,7,8]] 
; N = 2, Lss = [[1,2,3,4], [5,6,7,8]] 
; N = 3, Lss = [[1,2], [3,4], [5,6,7,8]] 
; N = 4, Lss = [[1,2], [3,4], [5,6], [7,8]] 
; N = 5, Lss = [[1], [2], [3], [4], [5,6,7,8]] 
; N = 6, Lss = [[1], [2], [3], [4], [5], [6,7,8]] 
; N = 7, Lss = [[1], [2], [3], [4], [5], [6], [7,8]] 
; N = 8, Lss = [[1], [2], [3], [4], [5], [6], [7], [8]] 
; false. 
2

的你展示的例子(所有列表可以覆蓋

split(L, N, S) :- 
    length_list(N, S), 
    append(S, L), 
    maplist(length_list(_), S). 

length_list(Length, List) :- length(List, Length).