让我们从一个好的名称开始!
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]]).
现在查询的问题是:这里有所有的三元组,对应的元素是什么?“Elements”这个词太长了,用“els”也很好。
es_trigroups(Es, Ess) :-
phrase(seqq(Ess), Es).
请注意变量名称:
Es
:一个
E
的列表。而
Ess
是一个
E
的列表,这个列表又是
E
的列表。
使用在另一个答案中定义的seqq//1
。
该死,它仍然成功地执行了:
?- es_trigroups([1,2,3,4,5], [Es,Fs]).
Es = [], Fs = [1,2,3,4,5]
但这并不是很糟糕,因为它能够满足您所需的所有情况。简而言之:这种关系太笼统了,我们需要将其专业化。
专业化关系的简单方法是添加进一步的目标,例如:
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).
得出的终止条件如下:
es_trigroups(A,B)在b(B)的情况下终止。
% 最优。 找到循环:[es_trigroups(_,[[_,_,_|_]|_]),es_trigroups(y,[[_,_,_|_]|_])]. NTI花费了0ms,74i,74i
es_trigroups_bis(A,B)在b(B)的情况下终止。
% 最优。 找到循环:[es_trigroups_bis(_,[[]|_]),es_trigroups_bis(y,[[]|_])]. NTI花费了0ms,79i,79i
但是实际上我们想要的是,终止条件不仅取决于B
(第二个参数),还取决于单独的A
。也就是说,要么A
要么B
可以保证终止。为此,我们必须交错两个定义:
es_trigroups_ter(Es, Ess) :-
phrase(seq3s(Ess), Es).
seq3s([]) --> [].
seq3s([Es|Ess]) --> {Es = [_,_,_|_]}, seq(Es), seq3s(Ess).
现在,终止条件优秀!
es_trigroups_ter(A,B) 如果 b(A);b(B) 终止。
% 最优。循环已找到:[es_trigroups_ter([A|_],[[A,_,_|_]|_])]. NTI 花费 0 毫秒,77i,77i