# Input a square matrix and return a list of the matrix entries read by antidiagonals

I have a square matrix: {{1,2,3},{4,5,6},{7,8,9}} and I want to get a list:

{1,2,4,3,5,7}

• related: 41362 – Kuba Jan 30 '15 at 11:11
• Oddly enough, I encountered this same need yesterday. Went with the Reverse and Diagonal approach. – Daniel Lichtblau Jan 31 '15 at 21:31

A straightforward and clear solution:

f[m_] := Flatten@Table[m[[j, i - j + 1]], {i, Length@m}, {j, i}]

f@{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
(* {1, 2, 4, 3, 5, 7} *)


A fast compiled version:

fc = Compile[{{m, _Integer, 2}},
Module[{n = Length@m, res, k = 0},
res = Array[0 &, Quotient[n (n + 1), 2]];
Do[res[[++k]] = m[[j, i - j + 1]], {i, Length@m}, {j, i}];
res], CompilationTarget -> "C", RuntimeOptions -> "Speed"];


One can also write unobvious fast uncompiled solution:

f2[m_] := With[{n = Length@m}, Flatten[m][[# + (n - 1) Quotient[#2 - #^2 + #, 2]]] &[
Round@Sqrt@N@#, #] &@Range[1, n^2 + n, 2]]

n = 1000;
m = RandomInteger[10, {n, n}];

fc[m] == f[m] == f2[m] == fm[m]
(* True *)

f[m]; // AbsoluteTiming
fc[m]; // AbsoluteTiming
f2[m]; // AbsoluteTiming
fm[m]; // AbsoluteTiming  (* ubpdqn *)
(* {1.263933, Null} *)
(* {0.035024, Null} *)
(* {0.118597, Null} *)
(* {0.310459, Null} *)

f[n_] := Join @@ (Thread[{Range[#], Range[#, 1, -1]}] & /@
Range[n]);
fm[mat_] := Extract[mat, f[Length[mat]]]


So,

m = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
fm[m]


yields:{1, 2, 4, 3, 5, 7}

f = Function[m,
Flatten[
Diagonal[Reverse[m, {2}], #] & /@ Range[Length[m], 0, -1]
]
]

f @ {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}

{1, 2, 4, 3, 5, 7}


Purely (sic) for @Mr.Wizard's entertainment... ;D

f @ m_ :=
m[[(#+#2-#3)/2,(2-#+#2+#3)/2]]&[#,#2,#2^2]&[#,Round@Sqrt@#]&[2#]& ~Array~
(#(#+1)/2&@Length@m)


f @ {{1,2,3},{4,5,6},{7,8,9}}
(* {1,2,4,3,5,7} *)


m = Range[49] ~Partition~ 7;
m // MatrixForm
f @ m


(* {1,2,8,3,9,15,4,10,16,22,5,11,17,23,29,6,12,18,24,30,36,7,13,19,25,31,37,43} *)


(with thanks to a couple of entries in the OEIS)

• It makes my head hurt trying to follow this. Mission accomplished I guess so +1. :-p – Mr.Wizard Jan 31 '15 at 11:45

another way. The idea is to take diagonal of each larger matrix. But need to rotate it by 90 degrees each time, hence the Reverse[Transpose@mat.

Flatten[(Diagonal@Reverse[Transpose@mat[[1;;#, 1;;#]]])& /@ Range[Length[mat]]]

(* {1, 2, 4, 3, 5, 7} *)


Yet another just for fun:

m = {{1,2,3},{4,5,6},{7,8,9}};

m[[-#, # ;; 1 ;; -1]] & ~Array~ Length@m ~Flatten~ {{2, 1}} // Reverse

{1, 2, 4, 3, 5, 7}


Extract enables you to prep the indices in advance.

entries[A_?SquareMatrixQ] :=
With[{indices = Flatten[
Table[{i, j - i + 1}, {j, Length[A]}, {i, j}], 1]},
Extract[A, indices]]

entries[{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}]
(* {1, 2, 4, 3, 5, 7} *)