Given a matrix like below, transform it, say, 90 degrees into the second matrix below. How would you go about doing this in the cleanest way possible? Short/succinct/clear solutions where the point is easy to grasp is preferred.
From
[[A1,A2,A3],
[B1,B2,B3],
[C1,C2,C3]]
To
[[A1,B1,C1],
[A2,B2,C2],
[A3,B3,C3]]
Edit: I realize it was not clear from original question. I'd like to know how to do this in Erlang.
Simplifying the solutions already given, you can do it in as short as:
-module(transp).
-export([transpose/1]).
transpose([[]|_]) -> [];
transpose(M) ->
[lists:map(fun hd/1, M) | transpose(lists:map(fun tl/1, M))].
In functional programming languages, the usual approach for matrix transposition is to use unzip
.
Here's my sample solution:
-module(transp).
-export([transpose/1]).
transpose(L) ->
transpose_do([], L).
transpose_do(Acc, [[]|_]) ->
lists:reverse(Acc);
transpose_do(Acc, M) ->
Row = lists:foldr(
fun(Elem, FoldAcc) ->
[hd(Elem) | FoldAcc]
end,
[],
M),
transpose_do([Row|Acc], lists:map(fun(X) -> tl(X) end, M)).
Test:
1> M = [[a1,a2,a3],[b1,b2,b3],[c1,c2,c3]].
[[a1,a2,a3],[b1,b2,b3],[c1,c2,c3]]
2> transp:transpose(M).
[[a1,b1,c1],[a2,b2,c2],[a3,b3,c3]]
Here's an implementation that I think I got from the Haskell standard library:
%% Transpose rows and columns in a list of lists. Works even if sublists
%% are not of same length. Empty sublists are stripped.
transpose([[X | Xs] | Xss]) ->
[[X | [H || [H | _] <- Xss]]
| transpose([Xs | [T || [_ | T] <- Xss]])];
transpose([[] | Xss]) -> transpose(Xss);
transpose([]) -> [].
Compact and slightly mind-bending.
What you are showing is not a matrix rotation, but rather matrix transposition. If you call the first matrix A and the second B then you have
A[i,j] = B[j,i]
To go from A to B you just need two nested loops with i = 1 to n and j = i+1 to n and at each iteration you swap the off-diagonal entries using a temporary variable.