6
$\begingroup$

Consider a matrix m as

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

In the matrix form this is (in my case)

enter image description here

Now I want to extract the boundary elements of this matrix at different levels as shown in different colors in the following image

enter image description here

How can I do this?

$\endgroup$
6
$\begingroup$

If the matrix is called A and if k is the depth then

Join[
 A[[k, k ;; -(k + 1)]],
 A[[k ;; -(k + 1), -k]],
 A[[-k, -k ;; k + 1 ;; -1]],
 A[[-k ;; k + 1 ;; -1, k]]
 ]

should provide you with the elements, starting in the top left in clockwise order.

$\endgroup$
5
$\begingroup$

Just for fun, here's a different solution:

pos[m_, {l1_, l2_}, dim_] := Position[
   CenterArray[ArrayPad[ConstantArray[1, {l1, l2}], 1], dim, 1],
   0
]

We can now specify any border using l1 and l2:

MapAt[Style[#, Red] &, m, pos[m, {2, 4}, Dimensions[m]]] // MatrixForm

Mathematica graphics

The {2, 4} denotes the dimension of the matrix inside the selected border. It has two rows and four columns.

This retrieves the elements:

Extract[m, pos[m, {2, 4}, Dimensions[m]]]
$\endgroup$
  • $\begingroup$ It would be great if the elements can be retrieved in a cyclic order. For example, in the given case your code returns 7,4,10,6,7,1,1,1,6,3,8,0,4,6,2,7. What I want is: 1,1,7,6,10,4,7,1,6,8,0,4,6,2,7 - starting from central right (1) and move anticlockwise. $\endgroup$ – Majis Feb 15 '18 at 12:51
  • $\begingroup$ @Majis I think you did the right thing by asking a separate question about this. If I think of an answer, I'll answer there. $\endgroup$ – C. E. Feb 15 '18 at 18:24
3
$\begingroup$
ClearAll[layerF, layerindicesF]
layerF[dims : {_, _}, {r_, c_}] := Module[{m = Array[1 &, dims]}, 
  ArrayPad[ArrayPad[m, {{-r + 1}, {-c + 1}}], {{r - 1}, {c - 1}}] - 
  If[ArrayPad[m, {{-r}, {-c}}]==={}, 0, ArrayPad[ArrayPad[m, {{-r}, {-c}}], {{r}, {c}}]]]
layerF[dims : {_, _}, r_Integer] := layerF[dims, {r, r}]
layerindicesF[dims : {_, _}, rc_] := Position[layerF[dims, rc], 1]

Examples:

layerF[{10, 10}, {2, 3}] /. 1 -> Style[1, 20, Red] // MatrixForm

enter image description here

layerindicesF[{10, 10}, 3]

{{3, 3}, {3, 4}, {3, 5}, {3, 6}, {3, 7}, {3, 8}, {4, 3}, {4, 8}, {5, 3}, {5, 8}, {6, 3}, {6, 8}, {7, 3}, {7, 8}, {8, 3}, {8, 4}, {8, 5}, {8, 6}, {8, 7}, {8, 8}}

SeedRandom[1]
m = RandomInteger[10, {10, 10}];
Extract[m, layerindicesF[{10, 10}, 3]]

{2, 6, 4, 5, 4, 3, 3, 9, 3, 4, 9, 10, 2, 1, 8, 6, 5, 6, 0, 10}

Grid[m, Background -> {None, None, 
   Join @@ (Thread[layerindicesF[{10, 10}, #] -> {Red, Orange, Yellow, Pink, 
    LightRed}[[#]]] & /@ Range[5])}, ItemSize -> {2, 2}, 
 Dividers -> All, ItemStyle -> Directive[20, Bold]]

enter image description here

Row[{MatrixForm[m], MatrixForm @ MapAt[Style[#, Red, Bold, 20] &,
    m layerF[Dimensions[m], 3], layerindicesF[Dimensions[m], 3]], 
  MatrixForm @ MapAt[Style[#, Red, Bold, 20] &, m, layerindicesF[Dimensions[m], 3]]}, 
  Spacer[5]]

enter image description here

Row[MatrixForm @ MapAt[Style[#, Red, Bold, 20] &, m layerF[Dimensions[m], #], 
   layerindicesF[Dimensions[m], #]] & /@ {{2, 4}, {1, 3}, {3, 2}}, Spacer[5]]

enter image description here

Note: C.E.'s method using CenterArray is much more elegant. However, it is available only in versions v11+. The method above works in version 9.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.