How can I generate a nested array like this one?
Via CellularAutomaton
:
ruleFn[{{_, _, _}, {_, 0, _}, {_, _, _}}, step_] := 1;
ruleFn[{{_, _, _}, {_, 1, _}, {_, _, _}}?(MemberQ[#, 0, 2] &), step_] := 0;
ruleFn[{{1, 1, 1}, {1, 1, 1}, {1, 1, 1}}, step_] := 1;
CellularAutomaton[{ruleFn, {}, {1, 1}}, {{{0}}, 1}, {{{9}}}] /. 1 -> "*" // Grid
Edit: For those who really like obfuscated CAs:
Grid[CellularAutomaton[
{6704108548762591141713703895184498446288891439307603869437298727894782281512658462491554691453382697921609151728673186802143641955019044568101339107753983,
2, {1, 1}}, {{{0}}, 1}, {{{9}}}] /. 1 -> "*"]
...or just like really large numbers.
Here's a recursive approach:
f[1] = {{1}};
f[x_] := ArrayPad[f[x - 1], 1, Boole@OddQ@x];
To apply it and display
f[8] //. 1 -> "*" // MatrixForm
I learned this trick from rm -rf in this post which has a great explanation of a simple recursive function. This f[ ]
works for both even and odd matrix sizes.
Update
Simpler way of generating a "concentric" matrix, without having to convert to an image to apply a distance transform:
With[{size = 11},
Array[Max[#1, #2, size + 1 - #1, size + 1 - #2] &, {size, size}]
/. {_?OddQ -> "0", _?EvenQ -> "*"}]
End update
Here's a hare-brained implementation that uses DistanceTransform[]
:
First create an image with a single background (value 0) pixel at the center, and remaining pixels all foreground (value 1):
img = Image[SparseArray[{6, 6} -> 0, {11, 11}, 1]]
Take the distance transform with the chessboard metric:
mat = Round@ImageData@DistanceTransform[img, DistanceFunction -> ChessboardDistance]
giving
Now simply use rule-based replacement
mat /. {_?EvenQ -> "*", _?OddQ -> "0"} // MatrixForm
to get the desired result.