Matrix 填充此矩阵的简单方法?

Matrix 填充此矩阵的简单方法?,matrix,wolfram-mathematica,fill,Matrix,Wolfram Mathematica,Fill,我想用以下方式填充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 _ _ _ 使用Mathematica做这件事的简单方法是什么?我不知道Mathematica

我想用以下方式填充
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  _   _   _

使用Mathematica做这件事的简单方法是什么?

我不知道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)
m=楼层(n/2)

num对角线上从1开始向右上的幻数可以从

f[n_] := 2 Sum[2 m - 1, {m, 1, n}] + UnitStep[n - 3] Sum[2 m, {m, 1, n - 2}]

In  := f@Range@5
Out := {2, 8, 20, 38, 62}

有了它,就可以很容易地设置
SparseArray
。我将仔细研究一下,看看这有多困难。

使用此帮助函数:

Clear[makeSteps];
makeSteps[0] = {};
makeSteps[m_Integer?Positive] :=
  Most@Flatten[
    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

部分解决方案,使用图像处理:

Image /@ (Differences@(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] :=
  ToRules@Reduce[
    -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], 
      N@(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]
i=10;
a=b=c=Array[0&,{2(2i+1),2(2i+1)}];
f[n_]:=3*n*(n+1)+1;
k=f[i-2];
p[i_整数]:=
ToRules@Reduce[
-x+y-i+1&&
(2 i+1-x)^2+(2 i+1-y)^2 x>i+1&&
3i-1>y>i+1,{x,y},整数];
((a[[Sequence@@@1]&/@({x,y}/{p[i]}));
((a[[Sequence@@(#+{2,2})]]=0&/@({x,y}/{p[i-1]}));
(b[[Sequence@@@k-)&/@(#+2i{1,1})和/@(SortBy[(#-2i{1,1})和/@)
位置[a,1],
N@(Mod[-10^-9-Pi/4+ArcTan[Sequence@@@#]、2pi])&);
c=表[b[[2(2 i+1)-j,k]],{j,2(2 i+1)-1},
{k,2(2i+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--];
   ];
  Return@MatrixForm[a];
  ]

genMat[5]
genMat[m!]:=Module[{f,k,k1,i,n,a={{1}},
f[n_]:=3*n*(n+1)+1;


对于[n=1,n我们可以假设
n
是奇怪的吗?@Szabolcs,对不起,你当然可以。只是好奇:你打算用这个做什么?@sjoard它涉及到项目Euler的一个问题,但不是关键。我发现如何有效地填充这个构造本身就是一个有趣的问题。而类似这样的问题当然可以,而且很简单,我认为问题的关键是如何利用Mathematica的内置功能和函数式编程contstructs来设计更简单、更紧凑的东西:-)当我独立完成我的版本时,我才意识到这是我最终使用的同一个算法,只是完成了过程性的LeoID我必须承认我在阅读这篇文章的过程中迷失了方向,并认为“我只等一个Mathematica的答案。”PeterT:+1,你可以把它减少到<代码> 2 - 3 n+3 n^ 2 < /代码>,更简单的是递归定义<代码> f[-1 ]=2;f[i]:=6i+f[i-1 ]。
像往常一样:)通过大反对角线@belisarius或
查找SequenceFunction[{2,8,20,38}]
向下移动,但这不容易相信(以下数字也会匹配吗?@Mr.Wizard我添加了一些explanation@Mr.Wizard可以删除双
transpose
并使用
{cycles+#,cycles-#}&
而不是
{#,-#}&
,以缩短代码,同时牺牲一些性能损失。那么
周期+{#,-#如何
?:-)你会感兴趣吗?@yoda问得好,一点也不容易。我认为应该试着识别旋转椭圆。如果你试一试的话会很好:)我甚至可以赏金让你振作起来:D有一些图像处理问题(),但没有足够的人知道答案。很多人只是给出了半途而废的答案…@yoda给出了部分答案谢谢,@bel。我会遵守我对赏金的承诺:)这看起来很有趣;你能解释一下吗?@先生,当前的代码版本仍然太复杂了。我一拿到som就把它清理干净并发表评论自由时间。这里有两个主要的想法(没有什么好主意):1)用几何方法描述“六边形”,让Reduce[]找到边,2)按照从多边形中心所对的角度对边元素进行排序。第三个想法不是我的f[n_u]:=3*n*(n+1)+1来自这里我无法想象这是高效的,但是+1是一种完全不同的方法。@先生,我想它最终会非常高效,因为一旦你画出来,几何描述非常简单。看看我的图片:4个直段和两个Pi/4楼梯。我将删除Reduce[]部分。然后我将去掉排序符[],因为我将按顺序构建边,并且我知道最大的数字是f[I-2]。因此它将是三个循环和O(n)。@先生,那么您现在可以享受了