我想通过以下方式来填充n * n
(n为奇数)矩阵:简单的方法来填充这个矩阵?
_ _ _ 23 22 21 20
_ _ 24 10 9 8 37
_ 25 11 3 2 19 36
26 12 4 1 7 18 35
27 13 5 6 17 34 _
28 14 15 16 33 _ _
29 30 31 32 _ _ _
什么是一个简单的方法来做到这一点使用数学?
我想通过以下方式来填充n * n
(n为奇数)矩阵:简单的方法来填充这个矩阵?
_ _ _ 23 22 21 20
_ _ 24 10 9 8 37
_ 25 11 3 2 19 36
26 12 4 1 7 18 35
27 13 5 6 17 34 _
28 14 15 16 33 _ _
29 30 31 32 _ _ _
什么是一个简单的方法来做到这一点使用数学?
有了这个辅助函数:
Clear[makeSteps];
makeSteps[0] = {};
makeSteps[m_Integer?Positive] :=
[email protected][
Table[#, {m}] & /@ {{-1, 0}, {-1, 1}, {0, 1}, {1, 0}, {1, -1}, {0, -1}}, 1];
我们可以构建矩阵
constructMatrix[n_Integer?OddQ] :=
Module[{cycles, positions},
cycles = (n+1)/2;
positions =
Flatten[FoldList[Plus, cycles + {#, -#}, makeSteps[#]] & /@
Range[0, cycles - 1], 1];
SparseArray[Reverse[positions, {2}] -> Range[Length[positions]]]];
要获得您所描述的矩阵,使用
constructMatrix[7] // MatrixForm
背后的想法这是检查连续数字1的位置跟随的模式。你可以看到这些形成了循环。第零个循环是微不足道的 - 在位置{0,0}
处包含数字1(如果我们从中心计数位置)。下一个循环是通过在位置{1,-1}
处获取第一个数字(2)并逐个添加以下步骤来形成的:{0, -1}, {-1, 0}, {-1, 1}, {0, 1}, {1, 0}
(当我们在中心附近移动时)。第二个周期是类似的,但我们必须从{2,-2}
开始,重复每个前面的步骤两次,并添加第六步(向上),只重复一次:{0, -1}
。第三个循环是类似的:从{3,-3}
开始,重复所有步骤3次,除了{0,-1}
,其仅重复两次。辅助功能makeSteps
使过程自动化。在主要功能中,我们必须将所有位置一起收集起来,然后将其添加到{cycles, cycles}
,因为它们是从位于中心的位置计算的,位置为{cycles,cycles}
。最后,我们构建了这些职位中的SparseArray
。
@ Mr.Wizard我加了一些解释 –
做得非常好。 –
@ Mr.Wizard One可以删除双重'Tranpose'并使用'{cycles +#,cycles - #}&'而不是'{#, - #}&'来缩短代码,代价是性能受损。 –
我不知道Mathematica的语法,但我想你可以使用一种算法是这样的:
start in the middle of the matrix
enter a 1 into the middle
go up-right (y-1/x+1)
set integer iter=1
set integer num=2
while cursor is in matrix repeat:
enter num in current field
increase num by 1
repeat iter times:
go left (x-1/y)
enter num in current field
increase num by 1
repeat iter times:
go down-left (x-1/y+1)
enter num in current field
increase num by 1
repeat iter times:
go down (x/y+1)
enter num in current field
increase num by 1
repeat iter times:
go right (x+1/y)
enter num in current field
increase num by 1
repeat iter times:
go up-right (x+1/y-1)
enter num in current field
increase num by 1
repeat iter-1 times:
go up (x/y-1)
enter num in current field
increase num by 1
go up-up-right (y-2/x+1)
increase iter by 1
你也可以很容易地转换算法成一个功能版本或成尾递归。如果你不超出界限,你将不得不在while循环中检查。如果n是奇数,那么你可以只计数NUM了,而:
m = floor(n/2)
num <= n*n - (m+m*m)
我敢肯定,有一个简单的算法,但是这是最直观的一个给我。
尽管类似这样的东西当然有用,而且很简单,但我认为问题的关键在于如何利用Mathematica的内置功能和函数式编程配置来创建更简单,更紧凑的东西:-) – Szabolcs
尽管我的版本独立的,我只是意识到,这是我结束了,相同的算法,只是程序上完成。 +1。 –
@Leonid我必须承认,在阅读本书的过程中我迷失了方向,并且认为“我只是等待一个* Mathematica *的答案。” PeterT:+1 –
在对角线上开始幻数为1,右往上走可以从
f[n_] := 2 Sum[2 m - 1, {m, 1, n}] + UnitStep[n - 3] Sum[2 m, {m, 1, n - 2}]
In := [email protected]@5
Out := {2, 8, 20, 38, 62}
可以带着这应该很容易建立一个SparseArray
。我会仔细研究一下,看看它有多难。
的部分解决方案,使用图像procssing:
Image /@ ([email protected](ImageData /@
NestList[
Fold[ImageAdd,
p = #, (HitMissTransform[p, #, Padding -> 0] & /@
{{{1}, {-1}},
{{-1}, {-1}, {1}},
{{1, -1, -1}},
{{-1, -1, 1}},
{{-1, -1, -1, -1}, {-1, -1, -1, -1}, {1, 1, -1, -1}},
{{-1, -1, -1, 1}, {-1, -1, -1, -1}, {-1, -1, -1, -1}}})] &, img, 4]))
第一版本:
i = 10;
a = b = c = Array[0 &, {2 (2 i + 1), 2 (2 i + 1)}];
f[n_] := 3*n*(n + 1) + 1;
k = f[i - 2];
p[i_Integer] :=
[email protected][
-x + y < i - 1 && -x + y > -i + 1 &&
(2 i + 1 - x)^2 + (2 i + 1 - y)^2 <= 2 i i - 2 &&
3 i - 1 > x > i + 1 &&
3 i - 1 > y > i + 1, {x, y}, Integers];
((a[[Sequence @@ #]] = 1) & /@ ({x, y} /. {p[i]}));
((a[[Sequence @@ (# + {2, 2})]] = 0) & /@ ({x, y} /. {p[i - 1]}));
(b[[Sequence @@ #]] = k--)&/@((# + 2 i {1, 1}) &/@ (SortBy[(# - 2 i {1, 1}) &/@
Position[a, 1],
[email protected](Mod[-10^-9 - Pi/4 + ArcTan[Sequence @@ #], 2 Pi]) &]));
c = Table[b[[2 (2 i + 1) - j, k]], {j, 2 (2 i + 1) - 1},
{k, 2 (2 i + 1) - 1}];
MatrixPlot[c]
编辑
一个更好的:
genMat[m_] := Module[{f, k, k1, i, n, a = {{1}}},
f[n_] := 3*n*(n + 1) + 1;
For[n = 1, n <= m, n++,
a = ArrayPad[a, 1];
k1 = (f[n - 1] + (k = f[n]) + 2)/2 - 1;
For[i = 2, i <= n + 1, i++, a[[i, 2n + 1]] = k--; a[[2-i+2 n, 1]] = k1--];
For[i = n + 2, i <= 2 n + 1, i++, a[[i, 3n+2-i]] = k--; a[[-i,i-n]] = k1--];
For[i = n, i >= 1, i--, a[[2n+1, i]] = k--;a[[1, -i + 2 n + 2]] = k1--];
];
[email protected][a];
]
genMat[5]
这看起来很有趣;你能解释一下吗? –
@Mr。目前的代码化身仍然过于复杂。只要有空闲时间,我会立即清理并发表评论。这里有两个主要思想(没有什么明显的):1)用几何形状描述“六边形”,让Reduce []找到边,2)按照从多边形中心对角的角度对边元素进行排序。第三个想法不是我的f [n_]:= 3 * n *(n + 1)+ 1来自https://oeis.org/search?q=crystal+ball&language=english&go=Search –
我无法想象这个效率很高,但采用完全不同的方法+1。 –
我们可以假定'N'是奇数? – Szabolcs
@Szabolcs,对不起,你当然可以。 –
只是好奇:你打算如何使用它? –