Prolog - 将列表划分为n元素部分

时间:2017-05-30 23:08:18

标签: prolog

我有一个预测,它获得前N个元素:

nfirst(N, _, Lnew) :- N =< 0, Lnew = [].
nfirst(_, [], []).
nfirst(N, [X|Y], [X|Y1]) :- N1 is N - 1, nfirst(N1, Y, Y1).

它有效:    %nfirst(3,[1,2,3,4,5,6],X)。    %X = [1,2,3]

我需要对下面的分组列表进行预测:

% divide([a,b,c,d,e,f,g,h],[3,2,1,2],X).
% X = [[a,b,c],[d,e],[f],[g,h]]

最好的方法是使用nfirst。

1 个答案:

答案 0 :(得分:4)

非常类似于I answered here的问题。同样,诀窍是使用append/3length/2来&#34;咬掉&#34;根据我上面的评论,一大块清单:

split_at(N, List, [H|[T]]) :- append(H, T, List), length(H, N).

如果你运行它,你会看到:

?- split_at(4, [1,2,3,4,5,6,7,8], X).
X = [[1, 2, 3, 4], [5, 6, 7, 8]] ;

所以这是你的程序的支柱,现在你只需要通常的递归东西。首先,基本情况说,如果我不在列表中,我应该在分割位置之外,因此不在结果中:

divide([], [], []).

请注意,像这样的显式基本情况会使您的程序比divide([], _, _)更正确,因为如果您的列表大小分割位置太多,它们将导致您失败。

现在递归的情况并不困难,但因为split_at/3将两个事物放在一个列表中(可能是一个糟糕的选择,你可以将split_at/4作为改进)你必须将它们拿出来,它在这里使逻辑略有不足,同时使(IMO)成为一个更好的API。

divide(List, [Split|Splits], [Chunk|Rest]) :-
    split_at(Split, List, [Chunk, Remainder]),
    divide(Remainder, Splits, Rest).

这应该相当简单:我们只需要Split位置,使用它来切断List,并重复处理剩下的内容。它似乎按预期工作:

?- divide([a,b,c,d,e,f,g,h],[3,2,1,2],X).
X = [[a, b, c], [d, e], [f], [g, h]] ;
false.

希望这有帮助!与其他答案相比,它可能会照亮事物。