Пролог объединяет два списка

Например, у меня есть A = [a,b,c,d] и B = [[q,w,e],[r,t],[y,u],[i,o]] и я хочу создать такие пары C = [[a,[q,w,e]],[b,[r,t]],[c,[y,u]],[d,[i,o]]]. Я могу создать список пар, но я не хочу объединять всех друг с другом. Есть ли простой способ сделать это? Я просто не могу правильно определить проблему для Google.


person JohnDow    schedule 30.05.2014    source источник


Ответы (3)


Эта задача мне кажется не очень понятной, но давайте попробуем:

Мое первое наблюдение состоит в том, что все три списка имеют одинаковую длину. И что фактически у вас есть здесь поэлементное отображение, подобное этому:

a_b_c(A,B,[A,B]).

Теперь используйте maplist/4:

?- As = [a,b,c,d], Bs = [[q,w,e],[r,t],[y,u],[i,o]], maplist(a_b_c, As, Bs, Cs).
As = [a,b,c,d],
Bs = [[q,w,e],[r,t],[y,u],[i,o]],
Cs = [[a,[q,w,e]],[b,[r,t]],[c,[y,u]],[d,[i,o]]].

Однако, осмелюсь сказать, я действительно рассматривал бы скорее пары! Я не вижу никаких достоинств в приведенном выше представлении.

key_value_pair(K,V,K-V).

?-  As = [a,b,c,d], Bs = [[q,w,e],[r,t],[y,u],[i,o]], maplist(a_b_c, As, Bs, Cs).
As = [a,b,c,d],
Bs = [[q,w,e],[r,t],[y,u],[i,o]],
Cs = [a-[q,w,e],b-[r,t],c-[y,u],d-[i,o]].

maplist/4 — это общий предопределенный или библиотечный предикат. см. также этот пост. Если у вас его нет:

maplist(_C_3, [], [], []).
maplist(Cont_3, [A|As], [B|Bs], [C|Cs]) :-
   call(Cont_3, A, B, C),
   maplist(Cont_3, As, Bs, Cs).
person false    schedule 30.05.2014

Я определил следующий предикат для решения этой задачи.

merge([X], [Y], [[X,Y]]).
merge([X|L1], [Y|L2], [[X,Y]|L3]):-merge(L1, L2, L3).

Первая строка — это факт. Результатом объединения двух списков с одним элементом в каждом является список, содержащий только один элемент, то есть список с двумя элементами X и Y.

Вторая строка гласит, что: результатом слияния двух списков, содержащих не менее двух элементов, является список, в котором первый элемент равен списку из двух элементов (первый элемент каждого списка), а остаток является результатом слияния остатка первые два списка.

ИЗМЕНИТЬ:

Если вы хотите обработать случай пустых списков, вы можете использовать это определение:

merge([X], [Y], [[X,Y]]):-!.
merge([], [], []).
merge([X|L1], [Y|L2], [[X,Y]|L3]):-merge(L1, L2, L3).

Это немного сложнее, поскольку в нем используется предикат cut !, чтобы прекратить поиск решений.

person rareyesdev    schedule 30.05.2014
comment
merge([], [], []). не удается? - person false; 30.05.2014
comment
@false, ты прав. Я решил пропустить угловые случаи, потому что вопрос не указывает этот случай. - person rareyesdev; 30.05.2014

Попробуйте что-то вроде этого:

zip( []     , [Y|Ys  , [ nil:Y | Zs ] ) :- % for lists of unequal length,
  zip( [] , Ys , Zs ) .                    %   create unmatched pairs and recurse down
zip( [X|Xs] , []     , [ X:nil | Zs ] ) :- % for lists of unqual lengths,
  zip( Xs , [] , Zs ) .                    %   create unmatched paris and recurs down
zip( [X|Xs] , [Y|Ys] , [ X:Y   | Zs ] ) :- % otherwise
  zip( Xs , Ys , Zs )                      % - pair up and recurse down.
  .                                        %

Другие стратегии работы со списками источников разной длины:

  • потерпеть неудачу
  • отбросить лишнее
person Nicholas Carey    schedule 30.05.2014
comment
Эта программа больше не обрабатывает nil правильно. Его представление называется по умолчанию. - person false; 31.05.2014