面试问题!
这就是你通常在Prolog中定义member
关系的方法:
member(X, [X|_]). % member(X, [Head|Tail]) is true if X = Head
% that is, if X is the head of the list
member(X, [_|Tail]) :- % or if X is a member of Tail,
member(X, Tail). % ie. if member(X, Tail) is true.
仅使用一个规则定义它。
答案 0 :(得分:36)
解决方案:
member(X, [Y|T]) :- X = Y; member(X, T).
演示:
?- member(a, []).
fail.
?- member(a, [a]).
true ;
fail.
?- member(a, [b]).
fail.
?- member(a, [1, 2, 3, a, 5, 6, a]).
true ;
true ;
fail.
工作原理:
X
中出现的第一个参数[Y|T]
。Y
匹配其头部,T
匹配尾部。X = Y
(即X
可以与Y
统一),那么我们会在列表中找到X
。否则(;
)我们会测试X
是否在尾部。说明:
=
(统一)会产生比使用==
更灵活的代码(测试相等性)。此代码也可用于枚举给定列表的元素:
?- member(X, [a, b]).
X = a ;
X = b ;
fail.
它可用于“枚举”包含给定元素的所有列表:
?- member(a, X).
X = [a|_G246] ;
X = [_G245, a|_G249] ;
X = [_G245, _G248, a|_G252] ;
...
在上面的代码中用=
替换==
会降低灵活性:它会在member(X, [a])
上立即失败并导致member(a, X)
上的堆栈溢出(使用SWI-Prolog版本5.6.57测试)。
答案 1 :(得分:20)
由于你没有指定我们允许使用的其他谓词,我将尝试作弊。 :P
member(X, L) :- append(_, [X|_], L).
答案 2 :(得分:7)
newmember(X, Xs) :-
phrase(( ..., [X] ),Xs, _).
使用
... --> [] | [_], ... .
实际上,以下定义还确保Xs
是一个列表:
member_oflist(X, Xs) :-
phrase(( ..., [X], ... ), Xs).
...
的上述定义的第一次出现在p。
David B. Searls,用明确的条款语法研究DNA的语言学。 NACLP 1989,第1卷。
答案 3 :(得分:-1)
您也可以尝试以下方法:
member(X,L) :- append(_,[X|_],L).