渦巻き配置。
n×nの配列に0〜n×n-1の整数列を中央から渦巻き状に配置する。
問題をくれた弟2に感謝。
やっぱりguiはつけてないのでこんな感じで使う。

>>> rollLayout(5)
[[20, 21, 22, 23, 24],
 [19, 6, 7, 8, 9],
 [18, 5, 0, 1, 10],
 [17, 4, 3, 2, 11],
 [16, 15, 14, 13, 12]]

偶数でもOK

>>> rollLayout(4)
[[12, 13, 14, 15],
 [11, 2, 3, 4],
 [10, 1, 0, 5],
 [9, 8, 7, 6]]

…このままだとあまりにもあまりなのでしょうがないから解説してやろう。

  • n×nの配列に0〜n×n-1の整数列を中央から右回転渦巻き状に配置する。
    • 出力は取り扱わない。とりあえず
  • スタートは取り合えず中央から右に。
  • サンプルとして5×5を想定し、こんな感じで並ぶのを想像する
[[20, 21, 22, 23, 24],
 [19,  6,  7,  8,  9],
 [18,  5,  0,  1, 10],
 [17,  4,  3,  2, 11],
 [16, 15, 14, 13, 12]]
  • 中央スタートで、次に進む方向に着目する。
  • すると、以下のような方向で進んでいることがわかる。
    • 右はr、左はl、上はu、下はd。
 [[r, r, r, r, r],
  [u, r, r, r, d],
  [u, u, r, d, d],
  [u, u, l, l, d],
  [u, l, l, l, l]]
  • 座標がわかりやすくしてみる
  0  1  2  3  4
0 r  r  r  r  r
1 u  r  r  r  d
2 u  u  r  d  d
3 u  u  l  l  d
4 u  l  l  l  l
  • 以下のようなことに気づく。
  • 対角線状に分割されている!
    • rとdはx座標>=y座標
    • lとuはx座標<y座標
  • さらに、
    • rとuはn-y座標<=x座標
    • dとlはn-y座標>x座標
  • ∴中央からはじめて進む方向がわかれば渦巻き状に配置できるんじゃね?
    • x座標かy座標がnより大きくなるか、0以下になったら終了?


と言う訳で以下ソースコードPythonだが。
最初のarrは配列の初期化。
roll関数は内部で呼ぶ再帰用関数。

def rollLayout(n):
    arr = [[None for j in range(n)] for i in range(n)]
    def roll(arr,m,y,x):
        arr[y][x] = m
        if y<x and n-y<=x: y = y+1 # down
        elif y<=x and n-y>x: x = x+1 # right
        elif y>=x and n-y<=x: x = x-1 # left
        elif y>x and n-y>x: y = y-1  # up
        if 0 <= y < n and 0 <= x < n:
            roll(arr,m+1,y,x)
    roll(arr,0,n/2,n/2)
    return arr