vectores una transpuesta pseudocodigo multiplicacion matriz matrices matematicas definicion list matrix prolog flip transpose

list - una - vectores y matrices definicion



Cómo transponer una matriz en prólogo (7)

¿Cómo puedo transponer una lista como [[1,2,3][4,5,6][6,7,8]] a [[1,4,6],[2,7,8],[3,6,9]] ?

Para representarlo: me gustaría voltear la matriz 90 grados hacia la izquierda. ¿Cómo puedo hacer eso?


Aquí hay un fragmento de una respuesta más grande :

% transposed(+A, ?B) iff matrix B is transposed matrix A transposed(A, B) :- transposed(A, [], B). transposed(M, X, X) :- empty(M), !. transposed(M, A, X) :- columns(M, Hs, Ts), transposed(Ts, [Hs|A], X). % empty(+A) iff A is empty list or a list of empty lists empty([[]|A]) :- empty(A). empty([]). % columns(+M, ?Hs, ?Ts) iff Hs is the first column % of matrix M and Ts is the rest of matrix M columns([[Rh|Rt]|Rs], [Rh|Hs], [Rt|Ts]) :- columns(Rs, Hs, Ts). columns([[]], [], []). columns([], [], []).


Esta es la respuesta más corta que pude encontrar. Sin embargo, podría mejorarse usando listas de diferencias para permitir la recursión final.

transpose([[]|_], []). transpose(M, [X|T]) :- row(M, X, M1), transpose(M1, T). row([], [], []). row([[X|Xs]|Ys], [X|R], [Xs|Z]) :- row(Ys, R, Z).


Mi solución con nombres completos para una mejor comprensión:

% emptyMatrix(Line, EmptyMatrix) emptyMatrix([],[]). emptyMatrix([_|T1],[[]|T2]):-emptyMatrix(T1,T2). % only length of parameter ''Line'' is interesting. It ignores its content. % appendElement(Element, InputList, OutputList) appendElement(E,[],[E]). appendElement(E,[H|T],[H|L]):-appendElement(E,T,L). % appendTransposed(NestedList, InputMatrix, OutputMatrix) appendTransposed([],[],[]). appendTransposed([X|T1],[],[[X]|T3]):-appendTransposed(T1,[],T3). appendTransposed([X|T1],[R|T2],[C|T3]):-appendElement(X,R,C),appendTransposed(T1,T2,T3). % transposeMatrix(InputMatrix, TransposedMatrix) transposeMatrix([L|M],T):-emptyMatrix(L,A),transpose([L|M],T,A). transpose([],T,T). transpose([L|M],T,A):-appendTransposed(L,A,B),transpose(M,T,B).

Una ''línea'' puede ser un col o una fila.

La idea radica en agregar los elementos en las listas de una matriz vacía. (por ejemplo, todos los elementos de la primera fila = los primeros elementos de todas las columnas => todos los elementos de la primera fila i-ésima = los elementos i-ésima de todas las columnas)

Funciona en mi máquina como me muestra este protocolo de sesión:

5 ?- transposeMatrix([[1,2],[3,4]],T). T = [[1, 3], [2, 4]] ; false. 6 ?- transposeMatrix([[1],[2]],T). T = [[1, 2]] ; false. 7 ?- transposeMatrix([[1,2,3],[4,5,6]],T). T = [[1, 4], [2, 5], [3, 6]] ; false. 8 ?- transposeMatrix([[1]],T). T = [[1]] ; false.


No estoy seguro de que tu ejemplo sea correcto, pero entiendo la idea.

Si usa SWI-PROLOG, puede usar el módulo CLPFD , así:

:- use_module(library(clpfd)).

Permitiéndole usar el predicado transpose/2 , como este:

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

De lo contrario (si no hay SWI-PROLOG), simplemente podría usar esta implementación (que resultó ser una antigua en clpfd de SWI):

transpose([], []). transpose([F|Fs], Ts) :- transpose(F, [F|Fs], Ts). transpose([], _, []). transpose([_|Rs], Ms, [Ts|Tss]) :- lists_firsts_rests(Ms, Ts, Ms1), transpose(Rs, Ms1, Tss). lists_firsts_rests([], [], []). lists_firsts_rests([[F|Os]|Rest], [F|Fs], [Os|Oss]) :- lists_firsts_rests(Rest, Fs, Oss).

Para obtener una versión actualizada que usa incorporados foldl y maplist, consulte clpfd.pl .


Otro enfoque:

delete_one_list([], []). delete_one_list([[_|L]|LLs], [L|Ls]) :- delete_one_list(LLs, Ls). transpose_helper([], []). transpose_helper([[X|_]|Xs], [X|Ys]) :- transpose_helper(Xs, Ys). transpose([[]|_], []). transpose(List, [L|Ls]) :- transpose_helper(List, L), delete_one_list(List, NewList), transpose(NewList, Ls).


Un enfoque iterativo:

trans([H|R],[H1|R1]):-trans2([H|R],[H|R],[],[H1|R1],0),!. trans2([A|_],_,_,[],N):-length(A,N). trans2(M,[],H1,[H1|R1],N):-N1 is N+1, trans2(M,M,[],R1,N1). trans2(M,[H|R],L,[H1|R1],N):-nth0(N,H,X), append(L,[X],L1),trans2(M,R,L1,[H1|R1],N).


enfoque más simple:

trans(M, [P|T]):- first(M, P, A), trans(A, T). trans(Empty, []):- empty(Empty). empty([[]|T]):- empty(T). empty([[]]). first([[P|A]|R], [P|Ps], [A|As]):- first(R, Ps, As). first([], [], []).

eficiente también

[debug] 36 ?- time(trans([[1,2,3],[4,5,6],[7,8,9]],A)). % 21 inferences, 0.000 CPU in 0.000 seconds (?% CPU, Infinite Lips) A = [[1,4,7],[2,5,8],[3,6,9]] ; % 12 inferences, 0.000 CPU in 0.000 seconds (?% CPU, Infinite Lips) false.