2014-11-21 34 views
5

我试图做一个函数,将可变长度的列表按顺序分成三个长度均匀的列表。以下内容将其分成三部分,但进程会一次将它们插入到每个列表中。使用Prolog将单个列表拆分为三个

的我想要的一个例子是:

[1, 2, 3, 4, 5] -> [1, 2], [3, 4], [5] 

另一个例子是:

div([], [], [], []). 
div([X], [X], [], []). 
div([X,Y], [X], [Y], []). 
div([X,Y,Z|End], [X|XEnd], [Y|YEnd], [Z|ZEnd]):- 
    div(End, XEnd, YEnd, ZEnd). 

[8, 7, 6, 5, 4, 3, 2, 1] -> [8, 7, 6], [5, 4, 3], [2, 1]. 

下面的代码通过一次插入到每个列表中的一个分裂他们

此代码输出:

[1, 2, 3, 4, 5] -> [1, 4], [2, 5], [3] 

我该如何解决这个问题?

回答

5

@Boris的回答在第一个参数列表的长度未知时不会终止。看到这一点,就没有必要看任何进一步的比用第一个目标:

 
div(L, L1, L2, L3) :- 
    length(L, Len), false, 
    % here you compute for example Len1 and Len2 
    length(L1, Len1), 
    length(L2, Len2), 
    append(L1, L1_suffix, L), 
    append(L2, L3, L1_suffix). 

在另一方面,原来的程序有quite nice termination properties。 CTI提供了以下最佳的终止性质:

div(A,B,C,D) terminates_if b(A);b(B);b(C);b(D). 

换句话说,确保终止,你只需要一个参数(或ABCD)是一个具体的列表是有限的,地(这就是b(..)的含义)。这是一个非常强大的终止条件。真的很可惜,这些论点不合适!为什么不推广你的程序?唯一的问题是它限制了列表元素。因此,我将通过_小号替换列表元素的所有变量名:

gdiv([], [], [], []). 
gdiv([_], [_], [], []). 
gdiv([_,_], [_], [_], []). 
gdiv([_,_,_|End], [_|XEnd], [_|YEnd], [_|ZEnd]):- 
    gdiv(End, XEnd, YEnd, ZEnd). 

very same终止性质保持这个程序。

唉,现在有点太笼统了。鲍里斯的解决方案,现在可以改变用途:

divnew(Zs, As, Bs, Cs) :- 
    gdiv(Zs, As, Bs, Cs), 
    append(As, BsCs, Zs), 
    append(Bs, Cs, BsCs). 

我要表达同样的首选方式宁愿:

divnew(Zs, As, Bs, Cs) :- 
    gdiv(Zs, As, Bs, Cs), 
    phrase((seq(As), seq(Bs), seq(Cs)), Zs). 

seq//1定义见other answers

+0

谢谢@false。我也明白你在这个问题之外想要告诉我什么。 – Mocking 2016-04-15 05:26:27

2
div(L, L1, L2, L3) :- 
    append(L1, L1_suffix, L), 
    append(L2, L3, L1_suffix). 

你看这是如何分割三个列表?现在你没有说你期望列表L1L2L3是多长。如果您不希望谓词像现在一样普遍,则可以使用length/2来获得L的长度并设置三个结果的长度。由于你说的“相对均匀的长度”,这是相对的,我需要以某种方式解释它,假设你的意思是,对于一个正整数len和n,len = 3n,你得到len1 = len2 = len3 = len2 = len2 = len3 = len2 = len3 = len3 = len2 = len3 = n,对于k = 3n + 1,你得到len1 = n + 1,len2 = len3 = n,对于k = 3n + 2,你得到len1 = len2 = n + 1,len3 = n。我让你弄清楚如何计算长度。

div(L, L1, L2, L3) :- 
    length(L, Len), 
    % here you compute for example Len1 and Len2 
    length(L1, Len1), 
    length(L2, Len2), 
    append(L1, L1_suffix, L), 
    append(L2, L3, L1_suffix). 
+0

我不是100%确定,但我认为你误解了我的问题。我试图将第一个列表分成3个列表。 – Mocking 2014-11-21 09:36:50

+0

@Mocking你真的尝试过这个谓词吗?此外,仍然不清楚是否对结果列表的长度有任何限制。 – 2014-11-21 09:38:33

+0

对不起,我试图让我的问题更清楚。我试图将可变长度的列表分成3个甚至(或相对均匀)的列表。这实际上有助于这种情况吗? – Mocking 2014-11-21 09:46:22