List 序言:在列表中,在给定元素之后查找元素
我最近开始用Prolog编程,目前正在尝试创建规则,在列表中的给定元素之后查找该元素。例如,我希望List 序言:在列表中,在给定元素之后查找元素,list,prolog,List,Prolog,我最近开始用Prolog编程,目前正在尝试创建规则,在列表中的给定元素之后查找该元素。例如,我希望find(2,X,[1,2,3,4])。得到3 我迄今为止的努力: find(X,Y,[X,Y|Tail]):- !. find(X,Y,[_|Tail]):- find(X,Y,Tail). 这是一个没有剪辑的版本: find(X,Y,[X,Y|_]). find(X,Y,[Z|Tail]) :- X\=Z, find(X,Y,Tail). 以下是一个纯版本: find(
find(2,X,[1,2,3,4])。
得到3
我迄今为止的努力:
find(X,Y,[X,Y|Tail]):-
!.
find(X,Y,[_|Tail]):-
find(X,Y,Tail).
这是一个没有剪辑的版本:
find(X,Y,[X,Y|_]).
find(X,Y,[Z|Tail]) :-
X\=Z, find(X,Y,Tail).
以下是一个纯版本:
find(X,Y, [X,Y|_]).
find(X,Y, [X0,Y0|Xs]) :-
dif(X+X0,Y+Y0),
find(X,Y, [Y0|Xs]).
我更希望有一个确定性的版本,而且一个纯DCG版本会很酷 让我们使用
if_uu/3
和(=)/3
(也称为相等的真相/3
),如@false in
因此,新的,逻辑上纯粹的find/3
:
find(E0,E1,[X|Xs]) :-
member_next_prev_list(E0,E1,X,Xs).
member_next_prev_list(E0,E1,X0,[X1|Xs]) :-
if_(X0=E0, X1=E1, member_next_prev_list(E0,E1,X1,Xs)).
findB(E0,E1,[X0,X1|Xs]) :-
if_(X0=E0, X1=E1, findB(E0,E1,[X1|Xs])).
让我们运行OP/其他答案/一些评论中提到的查询:
?- find(a,X,[a,a,b]).
X = a. % succeeds deterministically
?- find(a,X,[a,Y,b]).
X = Y. % succeeds deterministically
?- find(a,b,[a,a,b]).
false. % fails
?- find(a,X,[a,a,b,c]).
X = a. % succeeds deterministically
?- find(b,X,[a,a,b,c]).
X = c. % succeeds deterministically
编辑2015-05-06 这里有一个更为简洁的变体,它被称为
findB/3
:
find(E0,E1,[X|Xs]) :-
member_next_prev_list(E0,E1,X,Xs).
member_next_prev_list(E0,E1,X0,[X1|Xs]) :-
if_(X0=E0, X1=E1, member_next_prev_list(E0,E1,X1,Xs)).
findB(E0,E1,[X0,X1|Xs]) :-
if_(X0=E0, X1=E1, findB(E0,E1,[X1|Xs])).
当我尝试时,你的代码运行良好。什么对你不起作用?澄清1:所谓确定性,我的意思是没有不必要的选择点。确实,仍然有一些情况需要选择点,比如
find(X,Y,X)
。应该有这样一个概念。反例:find(a,b,[a,a,b])
应该成功,但您的定义失败。更正:这个反例不正确。在原始问题的意义上,它确实应该在这里失败…确定性版本应该如何处理查找(a,X,[a,a,b])
?(在我的意义上)它应该找到两个答案-但是(现在我意识到)-在原始意义上,它应该只是X=a
。有没有更紧凑或可重用的方式来表达这一点?很难说两者之间的实际抽象应该是什么,但当前的方法没有产生任何可重用的元素。是的,确实如此。这正是谓词。
findC(E0,E1,[X0|XXs]) :-
XXs = [X1|_],
if_(X0=E0, X1=E1, findC(E0,E1,XXs)).