web-dev-qa-db-ja.com

メンバー述語をワンライナーとして実装する

インタビューの質問!

これは通常、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.

1つのルールのみを使用して定義します。

28
Claudiu
  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. 使い方:

    • 2番目の引数_[Y|T]_で最初の引数Xの出現を探しています。
    • 2番目の引数はリストと見なされます。 Yは頭に一致し、Tは尾に一致します。
    • その結果、空のリストの述語は(必要に応じて)失敗します。
    • _X = Y_(つまり、XYと統合できる)の場合、リストにXが見つかりました。そうでなければ(_;_)Xが末尾にあるかどうかをテストします。
  4. 備考:

    • _=_(統一)を使用すると、_==_(同等性のテスト)を使用するよりも柔軟なコードが生成されることを指摘してくれた hum​​ble coffee に感謝します。
    • このコードは、特定のリストの要素を列挙するためにも使用できます。

      _?- 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)。

36
Stephan202

使用を許可されている他の述語を指定しなかったので、少しだましてみます。 :P

member(X, L) :- append(_, [X|_], L).
20
bcat
newmember(X, Xs) :-
   phrase(( ..., [X] ),Xs, _).

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

実際、次の定義は、Xsがリストであることも保証します。

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

謝辞

上記の...の定義の最初の出現は、pです。 205、注1の

David B. Searls、定型文法によるDNAの言語学の調査。 NACLP 1989、第1巻。

7
false