Bangun array simetris berikut
Pikiran saya agak mendung dan saya tidak bisa menunjukkan dengan tepat pola di sini yang akan memungkinkan saya untuk menulis potongan kode yang elegan untuk membangun matriks simetris berikut untuk ukuran tertentu n:
Misalnya, jika n=5:
{{0, f[1], f[6], f[9], f[5] },
{f[1], 0, f[2], f[7], f[10]},
{f[6], f[2], 0, f[3], f[8] },
{f[9], f[7], f[3], 0, f[4] },
{f[5], f[10], f[8], f[4], 0 }}
Dan jika n=9,
{{0, f[1], f[10], f[19], f[28], f[33], f[25], f[17], f[9] },
{f[1], 0, f[2], f[11], f[20], f[29], f[34], f[26], f[18]},
{f[10], f[2], 0, f[3], f[12], f[21], f[30], f[35], f[27]},
{f[19], f[11], f[3], 0, f[4], f[13], f[22], f[31], f[36]},
{f[28], f[20], f[12], f[4], 0, f[5], f[14], f[23], f[32]},
{f[33], f[29], f[21], f[13], f[5], 0, f[6], f[15], f[24]},
{f[25], f[34], f[30], f[22], f[14], f[6], 0, f[7], f[16]},
{f[17], f[26], f[35], f[31], f[23], f[15], f[7], 0, f[8] },
{f[9], f[18], f[27], f[36], f[32], f[24], f[16], f[8], 0 }}
Apakah Anda melihat polanya? Diagonal utama adalah nol. Kemudian diagonal sub-diagonal terisi secara berurutan, diikuti oleh sudut kanan atas. Kemudian diagonal sub-sub-diagonal terisi, diikuti oleh diagonal kanan-atas sub-lead, dan seterusnya ...
Jawaban
Inilah usaha sederhana saya:
qdMat[n_Integer?Positive] := Module[{id, mm},
id = Riffle @@ Reverse[MapAt[Reverse, TakeDrop[Range[n - 1], Quotient[n - 1, 2]], -1]];
mm = TakeList[Array[f, Binomial[n, 2]], id][[InversePermutation[id]]];
mm = PadRight[PadLeft[Reverse[Flatten[mm, {{2}, {1}}], 2], {Automatic, n}], {n, n}];
mm + Transpose[mm]]
Misalnya,
qdMat[6]
{{0, f[1], f[7], f[13], f[11], f[6]},
{f[1], 0, f[2], f[8], f[14], f[12]},
{f[7], f[2], 0, f[3], f[9], f[15]},
{f[13], f[8], f[3], 0, f[4], f[10]},
{f[11], f[14], f[9], f[4], 0, f[5]},
{f[6], f[12], f[15], f[10], f[5], 0}}
qdMat[9]
{{0, f[1], f[10], f[19], f[28], f[33], f[25], f[17], f[9]},
{f[1], 0, f[2], f[11], f[20], f[29], f[34], f[26], f[18]},
{f[10], f[2], 0, f[3], f[12], f[21], f[30], f[35], f[27]},
{f[19], f[11], f[3], 0, f[4], f[13], f[22], f[31], f[36]},
{f[28], f[20], f[12], f[4], 0, f[5], f[14], f[23], f[32]},
{f[33], f[29], f[21], f[13], f[5], 0, f[6], f[15], f[24]},
{f[25], f[34], f[30], f[22], f[14], f[6], 0, f[7], f[16]},
{f[17], f[26], f[35], f[31], f[23], f[15], f[7], 0, f[8]},
{f[9], f[18], f[27], f[36], f[32], f[24], f[16], f[8], 0}}
Jika kita menentukan elemen di baris pertama, baris yang tersisa diperoleh dengan rotasi sederhana + padding dan menambahkan 1 ke baris sebelumnya yang diputar / diisi:
ClearAll[firstRow, rotatePad, spiralMat]
firstRow = Module[{rng = Range[0, Floor[(# - 1)/2]]},
1 + Join[# If[OddQ @ #, Most @ rng, rng] , (# - 1) Reverse @ Rest @ rng]] &;
rotatePad = Fold[PadLeft, RotateRight[#, #2], Length[#] + {-#2, 1}] &;
spiralMat = MapIndexed[rotatePad[#, #2[[1]] - 1]&] @ NestList[#+1&, firstRow @ #, #-1]&;
Contoh:
Row[MatrixForm[spiralMat[#]] & /@ Range[5, 9], Spacer[5]]
MatrixForm[spiralMat[9] /. x_Integer?Positive :> f[x]]
MatrixForm[# + Transpose @ # & @ spiralMat[9] /. x_Integer?Positive :> f[x]]
Karena diagonal beralih dari sudut ke dekat dengan diagonal, tidak ada solusi yang bagus (atau setidaknya tidak ada solusi yang mudah). Kode berikut akan melakukan triknya. Anda harus melakukan segitiga bawah sendiri.
n=9;
m = ConstantArray[0, {n, n}];
initialxLeft = 2;
initialxRight = n;
leftOrRightToggle = "Left";
counter = 1;
While[initialxLeft <= initialxRight,
If[leftOrRightToggle == "Left",
{x, y} = {initialxLeft, 1};
initialxLeft++;
leftOrRightToggle = "Right",
{x, y} = {initialxRight, 1};
initialxRight--;
leftOrRightToggle = "Left"];
While[x <= n,
m[[y, x]] = counter;
counter++;
x++;
y++;
];
];
m
$$\left( \begin{array}{ccccccccc} 0 & f[1] & f[10] & f[19] & f[28] & f[33] & f[25] & f[17] & f[9] \\ 0 & 0 & f[2] & f[11] & f[20] & f[29] & f[34] & f[26] & f[18] \\ 0 & 0 & 0 & f[3] & f[12] & f[21] & f[30] & f[35] & f[27] \\ 0 & 0 & 0 & 0 & f[4] & f[13] & f[22] & f[31] & f[36] \\ 0 & 0 & 0 & 0 & 0 & f[5] & f[14] & f[23] & f[32] \\ 0 & 0 & 0 & 0 & 0 & 0 & f[6] & f[15] & f[24] \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & f[7] & f[16] \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & f[8] \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\ \end{array} \right)$$
Kegunaan: mulai dengan beberapa poin $(x,y)$. Pindahkan titik sepanjang diagonal dan gunakan penghitung untuk melacak hitungan saat ini. Saat menyentuh tepi, atur ulang kembali ke baris atas. leftOrRightToggle melacak jika Anda harus mulai dari diagonal utama atau dari sudut. initialxleft dan initialxRight melacak posisi x awal mulai dari diagonal utama atau sudut secara berurutan. Setelah initialxleft dan initialxRight bertemu, Anda telah selesai.