32

面试题!

这是您通常member在 Prolog 中定义关系的方式:

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.

仅使用一个规则来定义它。

4

4 回答 4

40
  1. 解决方案:

    member(X, [Y|T]) :- X = Y; member(X, T).
    
  2. 示范:

    ?- member(a, []).
    fail.
    ?- member(a, [a]).
    true ;
    fail.
    ?- member(a, [b]).
    fail.
    ?- member(a, [1, 2, 3, a, 5, 6, a]).
    true ;
    true ;
    fail.
    
  3. 这个怎么运作:

    • 我们正在寻找第一个参数 ,X在第二个参数中的出现[Y|T]
    • 假定第二个参数是一个列表。Y匹配它的头,T匹配它的尾巴。
    • 结果,空列表的谓词失败(应该如此)。
    • 如果X = Y(即X可以与 统一Y)那么我们X在列表中找到了。否则 ( ;) 我们测试是否X在尾部。
  4. 评论:

    • 感谢谦虚的咖啡指出使用=(统一)产生的代码比使用==(测试相等)更灵活。
    • 此代码还可用于枚举给定列表的元素:

      ?- 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 测试)。

于 2009-11-16T19:24:48.873 回答
23

由于您没有指定我们允许使用的其他谓词,所以我将尝试作弊。:P

member(X, L) :- append(_, [X|_], L).
于 2009-11-17T00:11:51.447 回答
7
newmember(X, Xs) :-
   phrase(( ..., [X] ),Xs, _).

... --> [] | [_], ... .

实际上,以下定义也确保它Xs是一个列表:

member_oflist(X, Xs) :-
   phrase(( ..., [X], ... ), Xs).

致谢

上述定义的第一次出现...是在 p 上。205,注 1

David B. Searls,用定从句语法研究 DNA 的语言学。NACLP 1989,第 1 卷。

于 2012-07-31T12:17:09.920 回答
-3

你也可以试试这个:

member(X,L) :- append(_,[X|_],L).
于 2020-03-24T20:01:25.117 回答