Подтвердить что ты не робот

Реализуйте предикат члена как одну строку

Интервью вопрос!

Вот как вы обычно определяете отношение 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.

Определите его, используя только одно правило.

4b9b3361

Ответ 1

  • Решение:

    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 0,57).

Ответ 2

Поскольку вы не указали, какие другие предикаты нам разрешено использовать, я попытаюсь немного обмануть. :P

member(X, L) :- append(_, [X|_], L).

Ответ 3

newmember(X, Xs) :-
   phrase(( ..., [X] ),Xs, _).

С

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

На самом деле, следующее определение также гарантирует, что Xs является списком:

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

Подтверждения

Первое появление приведенного выше определения ... на с. 205, примечание 1 к

Дэвид Б. Сирлс, "Изучение лингвистики ДНК с помощью грамматик с определенным предложением". НАКЛП 1989, Том 1.