Prolog返回一个列表,其中只包含与列表头部相等的元素

Eno*_*noy 5 prolog

您好我想问一下我有以下代码:

principio([],[]).
principio([H],[H]).
principio([H,_|_],[H]).
principio([H,H|C],P) :-
    principio([H|C],R),P=[H|R].
Run Code Online (Sandbox Code Playgroud)

我想要一种方法:

?- principio([222,333,101,202,12,222,13,222],X).

X = [222,222,222]
Run Code Online (Sandbox Code Playgroud)

但是在这一刻我只得到了头脑:

X = [222]
Run Code Online (Sandbox Code Playgroud)

因此,为了清楚起见,我希望:第一个元素的所有连续出现都作为列表.

我怀疑的是这个任务P=[H|R]为什么不放弃:

principio([H,H|C],P) :-
    principio([H|C],P)
Run Code Online (Sandbox Code Playgroud)

另外,你会如何修改它以获得我要求的结果?谢谢

fal*_*lse 6

以下是两种缩小问题范围的方法.1,从意外失败的查询开始.2,从一个应该失败但是成功的查询开始.

1诊断意外的不完整性

确定最具体的失败查询

?- principio([222,333,101,202,12,222,13,222],[222,222,222]).
false.
Run Code Online (Sandbox Code Playgroud)

概括查询

... 越多越好.我可以手动完成,或者我可以让Prolog为我做这项工作.我在这里使用library(diadem):

?- use_module(diadem).
   true.

?- principio([222,333,101,202,12,222,13,222],[222,222,222]).? Gen.
   Gen = principio([222, 333|_], [_, _|_])
;  Gen =  (dif(A100, B100), principio([A100, B100|_], [_, _|_]))
...
Run Code Online (Sandbox Code Playgroud)

换句话说:您的原始查询不仅会失败,而且这种泛化也会失败!在这里,我们只坚持前两个元素是不同的,结果列表包含至少两个元素 - 无论哪个!

?- dif(X, Y), principio([X,Y|_],[_,_|_]).
Run Code Online (Sandbox Code Playgroud)

概括你的程序

:- op(950, fy, *).
* _P_0.

principio([], _/*[]*/).
principio([_H], _/*[H]*/).
principio([H,_|_],[H]).
principio([H,H|C],P) :-
    * principio([H|C],R),
    * P=[H|R].

错误必须存在于程序的剩余部分中.无需进一步阅读!

问题是,对于以两个不同元素开头的列表,您只有该子句principio([H,_|_],[H])..所以这部分必须以某种方式推广.

第二次诊断意外的不健全

找到错误的另一种方法是从意外的解决方案开始:

?- principio([222,333,101,202,12,222,13,222],[222]).
true.         % incorrect !!
Run Code Online (Sandbox Code Playgroud)

然后尽可能减少查询的大小.

?- principio([222,222],[222]).
true.         % incorrect !!
Run Code Online (Sandbox Code Playgroud)

现在,false只要上面的查询成功,就专门化你的程序插入:

principio([],[]) : - false.
principio([H],[H]) :- false.
principio([H,_|_],[H]).
principio([H,H|C],P) :- false,
    principio([H|C],R),
    P=[H|R].

剩下的可见部分是罪魁祸首!我们必须修改它.它的内容是:

以两个元素开头的任何列表都对应于仅包含第一个元素的列表.

principio([],[]).
principio([H],[H]).
principio([H,D|Xs], [H|Hs]) :-
   dif(H,D),
   principio([H|Xs],[H|Hs]).
principio([H,H|Xs],[H|Hs]) :-
   principio([H|Xs],Hs).
Run Code Online (Sandbox Code Playgroud)