Implementazione del predicato simile a Transpose in Prolog
Sono abbastanza nuovo su Prolog, in realtà dopo 4 giorni mi sono imbattuto in un esercizio che afferma:
Dato un elenco di N elenchi con dimensioni N, ciascuno implementa un predicato chiamato reshape (X, Y) in modo che:
- Raccoglie i primi elementi di tutti gli elenchi in un elenco.
- Raccoglie i secondi elementi di tutti gli elenchi elenchi in un elenco.
- ...
- Raccoglie gli N elementi di tutti gli elenchi in un elenco.
- Raccoglie tutti gli elenchi di cui sopra in un nuovo elenco.
Un esempio potrebbe essere:
- rimodellare ([[1,2,3], [4,5,6], [7,8,9]], X )
- X = [[1,4,7], [2,5,8], [3,6,9]]
Quindi ecco la mia implementazione:
% Insert at the end of a list
insert([],X,[X]).
insert([H|T1],X,[H|T2]) :- insert(T1,X,T2).
% Length of list
len([],L,L).
len([_|T],L,X) :-
L1 is L + 1,
len(T,L1,X).
len(L,X) :- len(L,0,X).
% Create a list of N empty lists
init_list(L,0,L) :- !.
init_list(L,N,X) :-
N1 is N-1,
insert(L,[],Y),
init_list(Y,N1,X).
init_list(N,X) :- init_list([],N,X).
% Assign each element of a list to the corresponding list.
assign([],[],[]).
assign([H1|T1],[H2|T2],[Y|T3]) :-
insert(H2,H1,Y),
assign(T1,T2,T3).
% Reshape :
reshape([],L,L).
reshape([H1|T1],X,Result):-
assign(H1,X,Y),
reshape(T1,Y,Result).
reshape(Input,Result) :-
len(Input,N),
init_list(N,X),
reshape(Input,X,Result).
Quindi l'idea di base è che inizio creando una lista di N liste vuote e poi per ciascuna lista dico L dell'input assegno / aggiungo ogni elemento di L alla lista corrispondente.
Ora apprezzerei un contributo dato che ho già detto che sono nuovo di Prolog e non posso nemmeno dire quale sia la complessità temporale del mio predicato. L'unica cosa che so per certo è che funziona.
Tuttavia c'è un modo migliore per implementarlo?
Qual è la complessità temporale della mia implementazione? Sembra un tempo polinomiale ma non posso davvero dirlo.
Grazie in anticipo.
Risposte
Puoi codificare un algoritmo O (N) che attraversa ogni elemento una sola volta:
reshape([[]|Tail], []):-
maplist(=([]), Tail).
reshape(Input, [Result|RTail]):-
reshape(Input, LTail, Result),
reshape(LTail, RTail).
reshape([], [], []).
reshape([[Item|Tail]|LTail], [Tail|MTail], [Item|RTail]):-
reshape(LTail, MTail, RTail).
reshape/3ottiene l'elenco con ogni primo elemento dell'elenco di elenchi. Quindi reshape/2crea tutti questi elenchi in modo ricorsivo.
Scenario di test:
?- reshape([[1,2,3],[4,5,6],[7,8,9]],X).
X = [[1, 4, 7], [2, 5, 8], [3, 6, 9]] ;
false.