您好我想问一下我有以下代码:
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)
另外,你会如何修改它以获得我要求的结果?谢谢
以下是两种缩小问题范围的方法.1,从意外失败的查询开始.2,从一个应该失败但是成功的查询开始.
?- 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)