Prolog分成两个列表问题

Prolog分成两个列表问题,prolog,prolog-dif,dcg,Prolog,Prolog Dif,Dcg,我有一个序言作业 我需要查看列表中的第一个项目,看看下面的项目是否相同,直到它们不相同为止,然后按第一个项目及其副本将列表分开。e、 如果我的列表是a,a,a,b,c,它会把它分成第一个:a,a,a。第二:b,c 我当前的解决方案是有效的,除了最后一个匹配项进入第二个列表,而不是第一个列表。我似乎想不出办法让它出现在第一个列表中 grab([],[],[]). grab([A,A|L],[A|L2],Rest) :- grab([A|L],L2,Rest). grab([A|L],Init,[A

我有一个序言作业

我需要查看列表中的第一个项目,看看下面的项目是否相同,直到它们不相同为止,然后按第一个项目及其副本将列表分开。e、 如果我的列表是a,a,a,b,c,它会把它分成第一个:a,a,a。第二:b,c

我当前的解决方案是有效的,除了最后一个匹配项进入第二个列表,而不是第一个列表。我似乎想不出办法让它出现在第一个列表中

grab([],[],[]).
grab([A,A|L],[A|L2],Rest) :- grab([A|L],L2,Rest).
grab([A|L],Init,[A|L2]) :- grab(L,Init,L2).

当前两个元素不同时,不需要递归目标

grab([], [], []).
grab([A,A|Rest], [A|As], L2):- !, grab([A|Rest], As, L2).
grab([A|Tail], [A], Tail).
在你给出的定义中,你会得到许多不同的答案:

?- grab([a,a,a,b,c],Ys,Zs).
  Ys = [a, a], Zs = [a, b, c]
; Ys = [a],    Zs = [a, a, b, c]
; Ys = [a],    Zs = [a, a, b, c]
; Ys = [],     Zs = [a, a, a, b, c].

这里是另一个考虑到的解决方案。考虑到这种用法,
grab/3
对于第一个或第二个参数的空列表永远不会成功

grab([A], [A], []).
grab([A,B|Bs], [A], [B|Bs]) :-
   dif(A,B).
grab([A,A|Xs], [A|As], Bs) :-
   grab([A|Xs], As, Bs).

?- Xs = [A,B], grab(Xs,Ys,Zs).
  Xs = [A, B], Ys = [A],    Zs = [B], dif(A, B)
; Xs = Ys,     Ys = [B, B], Zs = [],  A = B
; false.
下面是一个使用s。最有趣的是这里使用的非终端不是上下文无关的。我将从一个过于笼统的尝试开始:

grab_tentative(Xs, Ys, Zs) :-
   phrase((seq(Ys),seq(Zs)), Xs).

seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).
grab_暂定/3
确保
Xs
Ys
Zs
串联而成。这太笼统了,但所有预期的解决方案都已经包括在内了

?- Xs = [A,B,C], grab_tentative(Xs,Ys,Zs).
   Xs = Zs, Zs = [A, B, C], Ys = []
;  Xs = [A, B, C], Ys = [A], Zs = [B, C]
;  Xs = [A, B, C], Ys = [A, B], Zs = [C]
;  Xs = Ys, Ys = [A, B, C], Zs = []
;  false.
第一个答案是,
Ys=[]
,但是(一直以来),
Ys
应该始终是非空列表,因此我们可以将答案限制为非空列表:

grab_tentative(Xs, Ys, Zs) :- Ys = [_|_], phrase((seq(Ys),seq(Zs)), Xs). 现在,答案已经好了一点:

?- Xs = [A,B,C], grab_tentative(Xs,Ys,Zs).
   Xs = [A, B, C], Ys = [A], Zs = [B, C]
;  Xs = [B, B, C], A = B, Ys = [B, B], Zs = [C]
;  Xs = Ys, Ys = [C, C, C], A = B, B = C, Zs = []
;  false.
第一个答案包括
A=B
。所以,它确实应该包含dif(A,B)。为此,我们需要引入这样一种背景。这里有一个方法可以做到这一点。请注意,
或_end//1
类似于
[]//0
,只是它确保了一些额外的条件

grab_final(Xs, Ys, Zs) :- Ys = [A|_], phrase((all_seq(=(A),Ys), or_end(dif(A)), seq(Zs)), Xs). or_end(C_1) --> call(cond_or_end(C_1)). % interface to predicates cond_or_end(_C_1, [], []). cond_or_end(C_1, [E|Es], [E|Es]) :-
谢谢,这很有道理@尼克:
grab([a],Ys,Zs)。
通过
Ys=[a],Zs=[]成功。您的问题陈述定义错误。一方面,你暗示
grab([],Xs,Ys)
应该为真,另一方面,你声明“需要查看列表中的第一项”,这意味着
grab/3
只能在包含至少一个元素的列表中成功。昨天,你问了一个类似的问题-得到了答案-并立即删除了你的问题。请注意,以这种方式,你可能会被禁止提问。我问的另一个问题的答案被删除了,然后没有答案,然后我意识到我的问题根本没有意义,所以重新提交了我的答案。我回答了它,我从未删除我的答案。但你们小组似乎删除了更多其他人回答的问题。这真的不好。我不知道发生了什么,但当我第一次看到答案时,当我重新加载时,没有答案。我问的问题没有任何意义,你给我的答案只是对解决方案的直接回答,而我并不想要这个答案。我不知道你对我的团队是什么意思?我不会删除我发布的问题或答案?我有一个健康的声誉,我一直在慢慢建立,从问题和答案,如果你看我的个人资料。
?- Xs = [A,B,C], grab_tentative(Xs,Ys,Zs).
   Xs = [A, B, C], Ys = [A], Zs = [B, C]
;  Xs = [B, B, C], A = B, Ys = [B, B], Zs = [C]
;  Xs = Ys, Ys = [C, C, C], A = B, B = C, Zs = []
;  false.
grab_final(Xs, Ys, Zs) :- Ys = [A|_], phrase((all_seq(=(A),Ys), or_end(dif(A)), seq(Zs)), Xs). or_end(C_1) --> call(cond_or_end(C_1)). % interface to predicates cond_or_end(_C_1, [], []). cond_or_end(C_1, [E|Es], [E|Es]) :-
?- Xs = [A,B,C], grab_final(Xs, Ys, Zs).
   Xs = [A, B, C], Ys = [A], Zs = [B, C], dif(A, B)
;  Xs = [B, B, C], A = B, Ys = [B, B], Zs = [C], dif(B, C)
;  Xs = Ys, Ys = [C, C, C], A = B, B = C, Zs = []
;  false.