Группировка элементов из 4 разных списков - PullRequest
5 голосов
/ 17 апреля 2019

У меня есть следующие 4 списка:

A= [1,2,3], 
B=[4,5,6], 
C=[7,8,9],
D=[10,11,12]

Я хочу получить другой список списков, первый элемент которого получает первый элемент каждого списка, второй элемент получает вторые элементы каждого списка и т. Д.Например:

[1,2,3], [4,5,6], [7,8,9], [10,11,12] 

становится

[[1,4,7,10], [2,5,8,11],[3,6,9,12]].

Я пытался использовать

findall([X,Y,Z,T],(member(X,A),member(Y,B),member(Z,C),member(T,D)),ModifiedList).

Но это не сработало.

Как можноя делаю это в Прологе?

Ответы [ 3 ]

5 голосов
/ 17 апреля 2019

Решение будет следующим:

% auxiliary predicate to group the first elements of
% all input lists and return the tails of the lists

group_first([], [], []).
group_first([[X| Xs]| Lists], [X| Tail], [Xs| Tails]) :-
    group_first(Lists, Tail, Tails).

% main predicate; we separate the first list from the other
% lists to take advantage of first-argument indexing

group([], []).
group([List| Lists], Groups) :-
    group(List, Lists, Groups).

group([], _, []).
group([X| Xs], Lists, [Group| Groups]) :-
    group_first([[X| Xs]| Lists], Group, Tails),
    group(Tails, Groups).

Пример вызова:

| ?- group([[1,2,3],[a,b,c],['A','B','C']], R).

R = [[1,a,'A'],[2,b,'B'],[3,c,'C']]
yes

Чтобы помочь понять решение:

| ?- group_first([[1,2,3],[a,b,c],['A','B','C']], Group, Tails).

Group = [1,a,'A']
Tails = [[2,3],[b,c],['B','C']]
yes
1 голос
/ 17 апреля 2019

то, что вы описываете, просто транспонировать / 2:

?- [library(clpfd)].
true.

?- transpose([[1,2],[3,4],[5,6]],T).
T = [[1, 3, 5], [2, 4, 6]].

Обратите внимание, что ответ Пауло интересен: вот его group_first / 3 в библиотеке (yall)

group_first(A,B,C) :- maplist([U,V,Z]>>(U=[X|Xs],V=X,Z=Xs),A,B,C).

или более эффективно

group_first(A,B,C) :- maplist([[X|Xs],X,Xs]>>true,A,B,C).

group / 2 довольно быстрее, чем clpfd: transpose:

?- N=100,length(M,N),maplist({N}/[R]>>length(R,N),M),time(group(M,T)).
% 20,402 inferences, 0.009 CPU in 0.009 seconds (100% CPU, 2165467 Lips)

?- N=100,length(M,N),maplist({N}/[R]>>length(R,N),M),time(transpose(M,T)).
% 30,708 inferences, 0.010 CPU in 0.010 seconds (100% CPU, 3192701 Lips)

и еще лучше в оригинальном ответе Пауло (group_first не указан):

?- N=100,length(M,N),maplist({N}/[R]>>length(R,N),M),time(group(M,T)).
% 10,302 inferences, 0.004 CPU in 0.004 seconds (100% CPU, 2513070 Lips)

и (почти) обратим:

?- group(T,[[1,2]]).
T = [[1], [2|_5420]].

Кажется хорошим кандидатом на получение запроса от библиотеки (clpfd) ...

0 голосов
/ 30 июня 2019

Вот еще один дубль:

nifty([], []).
nifty([[]|X], []) :-
   nifty(X, []).
nifty([], [[]|X]) :-
   nifty([], X).
nifty([[X|Y]|Z], [[X|Q]|R]) :-
   swap(Y, R, N),
   swap(Q, Z, M),
   nifty(M, N).

swap([], [], []).
swap([X|Y], [[X|P]|Q], [P|R]) :-
   swap(Y, Q, R).

Он занимает второе место по скорости:

?- dim(77,66,L), time((between(1,100,_), transpose(L,_), fail; true)).
% 1,577,201 inferences, 0.103 CPU in 0.104 seconds (99% CPU, 15244107 Lips)

?- dim(77,66,L), time((between(1,100,_), nifty(L,_), fail; true)).
% 521,601 inferences, 0.062 CPU in 0.063 seconds (99% CPU, 8368647 Lips)

?- dim(77,66,L), time((between(1,100,_), group(L,_), fail; true)).
% 528,300 inferences, 0.048 CPU in 0.049 seconds (98% CPU, 11105739 Lips)

Но он полностью двунаправленный, даже в SWI-Prolog:

Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.4)

?- nifty([[1,2,3],[4,5,6]],X).
X = [[1, 4], [2, 5], [3, 6]].

?- nifty([[1,4],[2,5],[3,6]],X).
X = [[1, 2, 3], [4, 5, 6]] ;
false.

?- nifty(X,[[1,2,3],[4,5,6]]).
X = [[1, 4], [2, 5], [3, 6]] ;
false.

?- nifty(X,[[1,4],[2,5],[3,6]]).
X = [[1, 2, 3], [4, 5, 6]].

И если система Prolog обеспечивает своевременную индексацию с несколькими аргументами, как в Jekejeke Prolog, она даже не оставляет точек выбора без особых сложностей:

Jekejeke Prolog 3, Runtime Library 1.3.8 (23 May 2019)

?- nifty([[1,2,3],[4,5,6]], X).
X = [[1,4],[2,5],[3,6]]

?- nifty([[1,4],[2,5],[3,6]], X).
X = [[1,2,3],[4,5,6]]

?- nifty(X, [[1,2,3],[4,5,6]]).
X = [[1,4],[2,5],[3,6]]

?- nifty(X, [[1,4],[2,5],[3,6]]).
X = [[1,2,3],[4,5,6]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...