Prolog:搜索长度> = 3的子列表

时间:2016-04-23 21:39:46

标签: list prolog

我想生成一个谓词,它能够检查列表是否会分成每个包含至少三个原子的子列表。

例如:

findgroups([1,2,3,4,5,6,7,8,9],L1).

有解决方案如:

L1=[[1,2,3],[4,5,6],[7,8,9]]
L1=[[1,2,3,4],[5,6,7,8,9]]
L1=[[1,2,3,4,5],[6,7,8,9]]
L1=[[1,2,3,4,5,6],[7,8,9]]

但是,以下内容将失败:

findgroups([1,2,3,4,5]).

我已经编写了一些基于使用append将列表拆分为两个子术语的谓词,但我对处理多个子列表感到困惑。

非常感谢您的帮助

祝福 Ĵ

2 个答案:

答案 0 :(得分:5)

让我们从一个好名字开始吧! findgroups/2这意味着你想要命令Prolog:Prolog确实找到了我的一些团体!快点!这真的很合适吗?我们来看看:

?- findgroups(L, [[1,2,3],[4,5,6],[7,8,9]]).

谁在这里找到任何一个团体?它们已经存在!所以你的名字真的是用词不当。相反,通过描述每个参数来撰写名称。第一个参数是关于列表,第二个是关于列表的列表。所以:

?- list_lists(L, [[1,2,3],[4,5,6],[7,8,9]]).

更好,但有点过于笼统。也许:

?- elements_trigroups(L, [[1,2,3],[4,5,6],[7,8,9]]).

所以查询现在读取:这里是所有的三元组,相应的元素是什么?元素是一个冗长的词,els也很好。

我的第一次(有点过于笼统)尝试:

es_trigroups(Es, Ess) :-
   phrase(seqq(Ess), Es).

请注意变量名称:EsE的列表。 EssEs的列表,而E依次是seqq//1的列表。

使用another answer中定义的?- es_trigroups([1,2,3,4,5], [Es,Fs]). Es = [], Fs = [1,2,3,4,5] ; Es = [1], Fs = [2,3,4,5] ; ...

Darn,它仍然成功:

es_trigroups(Es, Ess) :-
   trigroups(Ess),
   phrase(seqq(Ess), Es).

trigroups([]).
trigroups([Es|Ess]) :-
   Es = [_,_,_|_],
   trigroups(Ess).

但它并没有那么糟糕,因为它成功地满足了你所要求的所有情况。简介:这种关系太笼统了。我们需要专门化它。

专门化关系的一种简单方法是添加更多目标,例如:

es_trigroups_bis(Es, Ess) :-
   phrase(seqq(Ess), Es),
   trigroups(Ess).

所以现在一切似乎都很好。只有一件事,那不是很好:termination property可能会更好。有时我们需要交换目标。

B

结果终止条件为:

es_trigroups(A,B)terminates_if b(B).
    % optimal. loops found: [es_trigroups(_,[[_,_,_|_]|_]),es_trigroups(y,[[_,_,_|_]|_])]. NTI took    0ms,74i,74i
es_trigroups_bis(A,B)terminates_if b(B).
    % optimal. loops found: [es_trigroups_bis(_,[[]|_]),es_trigroups_bis(y,[[]|_])]. NTI took    0ms,79i,79i

但我们真正想要的是,终止条件不仅取决于A(第二个参数),还取决于A。也就是说,Bes_trigroups_ter(Es, Ess) :- phrase(seq3s(Ess), Es). seq3s([]) --> []. seq3s([Es|Ess]) --> {Es = [_,_,_|_]}, seq(Es), seq3s(Ess). 单独可以保证终止。为此,我们必须交织两种定义:

SessionManager

现在,终止条件为excellent

es_trigroups_ter(A,B)terminates_if b(A);b(B).
    % optimal. loops found: [es_trigroups_ter([A|_],[[A,_,_|_]|_])]. NTI took    0ms,77i,77i

答案 1 :(得分:0)

也许这个非常简单的解决方案可以做到

findgroups([], []).
findgroups(L, [[A,B,C|D]|Gs]) :-
    append([A,B,C|D], R, L),
    findgroups(R, Gs).

不要求最后一个解决方案,但这是正确的,因为您不排除只有一个元素的组

?- findgroups([1,2,3,4,5,6,7,8,9], Gs).
Gs = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] ;
Gs = [[1, 2, 3], [4, 5, 6, 7, 8, 9]] ;
Gs = [[1, 2, 3, 4], [5, 6, 7, 8, 9]] ;
Gs = [[1, 2, 3, 4, 5], [6, 7, 8, 9]] ;
Gs = [[1, 2, 3, 4, 5, 6], [7, 8, 9]] ;
Gs = [[1, 2, 3, 4, 5, 6, 7, 8|...]] ;
false.

为了完全匹配这些例子,我会写

findgroups(L, Gs) :- findgroups_(L, Gs), Gs = [_,_|_].
findgroups_([], []).
findgroups_(L, [[A,B,C|D]|Gs]) :-
    append([A,B,C|D], R, L),
    findgroups_(R, Gs).