Пролог: как найти определенный элемент в списке?

Я должен реализовать этот предикат:

predicate(+connections, +[index,position], -leftConnections);

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

(conn(symbol1, element11, element21), conn(symbol2, element12, element22), etc)

Я должен найти соединение, которое имеет символ, равный индексной переменной. Затем он должен проверить, какой из двух элементов равен переменной position, и сохранить другой (назовем его new_pos); затем удалите найденное соединение и найдите, какое из других соединений имеет любой из двух элементов, new_pos, и сохраните новый найденный символ.

Пример:

predicate([conn(1,P1,P2), conn(4,P2,P3), conn(3,P3,P1), conn(2,P6,P7)], [1, P2], left);

index = 1, position = P2 => new_position = P1 => new_symbol = 3
leftConnections = [conn(4,P2,P3), conn(3,P3,P1), conn(2,P6,P7)]

Код приветствуется!


person tasegula    schedule 14.05.2013    source источник
comment
Код оценен — что вы пробовали?   -  person Daniel Lyons    schedule 15.05.2013


Ответы (1)


Как и в любом языке программирования, вы должны разбить это на шаги. Первый шаг, по вашим словам, «найти соединение, которое имеет символ, равный индексной переменной».

Это довольно просто:

predicate(Connections, [Index,Position], Remaining) :-
    select(conn(Index, Position, _), Connections, Remaining).
predicate(Connections, [Index, Position2], Remaining) :-
    select(conn(Index, _, Position2), Connections, Remaining).

У обоих есть анонимная переменная, которая является new_pos, которую мы хотим сохранить, поэтому давайте ее сохраним:

predicate(Connections, [Index, Position], Remaining) :-
    select(conn(Index, Position, NewPos), Connections, Remaining).
predicate(Connections, [Index, Position2], Remaining) :-
    select(conn(Index, NewPos, Position2), Connections, Remaining).

Другой подход:

predicate(Connections, [Index, Position], Remaining) :-
    select(conn(Index, Position, NewPos), Connections, Remaining) ;
    select(conn(Index, NewPos, Position), Connections, Remaining).

На самом деле это было бы идеально, но нам нужно откуда-то вывести NewPos, иначе Пролог никогда не покажет нам, с чем он унифицирован.

select_position(Connections, [Index,Pos], Remaining, NewPos) :-
    select(conn(Index, Pos, NewPos), Connections, Remaining) ;
    select(conn(Index, NewPos, Pos), Connections, Remaining).

Следующим шагом будет поиск связи. Это тоже не сложно:

find_with_position(Position, Connections, Connection) :-
    member(Connection, Connections),
    (Connection = conn(_, Position, _) ;
     Connection = conn(_, _, Position)).

Оба они имеют некоторую логику особого случая для обработки того факта, что любой элемент может быть правильным. Вы можете рассмотреть возможность использования списков, чтобы вы могли просто использовать member.

Склеить их не сложно:

predicate(Connections, [Index, Position], Remaining, Target) :-
    select_position(Connections, [Index, Position], Remaining, NewPos),
    find_with_position(NewPos, Remaining, conn(Target,_,_)).

Попытайся:

?- predicate([conn(1,p1,p2), conn(4,p2,p3), 
              conn(3,p3,p1), conn(2,p6,p7)], [1, p2], Left, T).
Left = [conn(4, p2, p3), conn(3, p3, p1), conn(2, p6, p7)],
T = 3 ;
false.

У тебя тут много проблем. Если вы изучаете Prolog в классе, я рекомендую вам пройти обучение, например Изучите Prolog сейчас или Приключения Амзи.

person Daniel Lyons    schedule 15.05.2013
comment
Спасибо за ответ. Мне удалось сделать то, что я должен был получить, в вашем примере, conn(4,p2,p3) и иметь остаток: [conn(4,p2,p3), conn(3,p3,p1 ), conn(2,p6,p7)], который необходимо использовать следующим. - person tasegula; 18.05.2013