Пролог: в списке поиск элемента после данного элемента - PullRequest
12 голосов
/ 23 сентября 2011

Я недавно начал программировать на Прологе и сейчас пытаюсь создать правила, которые находят элемент после заданного элемента в списке.Например, я хочу, чтобы find(2,X,[1,2,3,4]). привел к 3.

Моя попытка пока:

find(X,Y,[X,Y|Tail]):-
   !.
find(X,Y,[_|Tail]):-
   find(X,Y,Tail).

Ответы [ 3 ]

6 голосов
/ 05 мая 2015

Давайте использовать if_/3 и (=)/3 (он же equal_truth/3), как определено @false в этот ответ !

Итак, вот новое, логическиpure 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)).

Давайте запустим запросы, упомянутые OP / другими ответами / некоторыми комментариями:

?- find(<b>a</b>,<i>X</i>,[<b>a</b>,<i>a</i>,b]).
<i>X</i> = <i>a</i>.                      % <b>succeeds deterministically</b>
?- find(<b>a</b>,<i>X</i>,[<b>a</b>,<i>Y</i>,b]).
<i>X</i> = <i>Y</i>.                      % <b>succeeds deterministically</b>
?- find(<b>a</b>,<i>b</i>,[<b>a</b>,<i>a</i>,b]).
false.                      % <b>fails</b>

?- find(<b>a</b>,<i>X</i>,[<b>a</b>,<i>a</i>,b,c]).
<i>X</i> = <i>a</i>.                      % <b>succeeds deterministically</b>
?- find(<b>b</b>,<i>X</i>,[a,a,<b>b</b>,<i>c</i>]).
<i>X</i> = <i>c</i>.                      % <b>succeeds deterministically</b>

Теперь к чему-то немного более общий:

?- find(<b>X</b>,<i>Y</i>,[<b>a</b>,<i>a</i>,<b>b</b>,<i>c</i>]).
<b>X</b> = <b>a</b>, <i>Y</i> = <i>a</i> ;
<b>X</b> = <b>b</b>, <i>Y</i> = <i>c</i> ;
false.

А как насчет самого общего запроса ?Поскольку код pure , мы получаем логически обоснованных ответов:

?- find(X,Y,List).
List = [            X,Y|_Z] ;
List = [_A,         X,Y|_Z], dif(_A,X) ;
List = [_A,_B,      X,Y|_Z], dif(_A,X), dif(_B,X) ;
List = [_A,_B,_C,   X,Y|_Z], dif(_A,X), dif(_B,X), dif(_C,X) ;
List = [_A,_B,_C,_D,X,Y|_Z], dif(_A,X), dif(_B,X), dif(_C,X), dif(_D,X) ...

Edit 2015-05-06

Вотболее краткий вариант, не имеющий обозначения findB/3:

findB(E0,E1,[X0,<b>X1|Xs</b>]) :-
   if_(X0=E0, X1=E1, findB(E0,E1,[<b>X1|Xs</b>])).

Подобно find/3, findB/3 эффективен в том смысле, что не оставляет позади бесполезные точки выбора, но имеет более высокое использование памяти.

findC/3 пытается уменьшить использование памяти, поднимая общее выражение [X1|Xs]:

findC(E0,E1,[X0|<b>XXs</b>]) :-
   XXs = [X1|_],
   if_(X0=E0, X1=E1, findC(E0,E1,<b>XXs</b>)).
2 голосов
/ 29 декабря 2011

Вот версия без надреза:

find(X,Y,[X,Y|_]).
find(X,Y,[Z|Tail]) :- 
    X\=Z, find(X,Y,Tail).
0 голосов
/ 05 мая 2015

Вот чистая версия:

find(X,Y, [X,Y|_]).
find(X,Y, [X0,Y0|Xs]) :-
   dif(X+X0,Y+Y0),
   find(X,Y, [Y0|Xs]).

Я бы предпочел иметь детерминированную версию, а также чистая версия DCG была бы крутой!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...