第3講 第2講の魔方陣を高速化しよう!
第2話 新しいセル位置番号付けはどうするか?
n = 3 のとき
0 | 1 | 2 | |
0 | 0 | 5 | 3 |
1 | 6 | 1 | 7 |
2 | 4 | 8 | 2 |
n = 4 のとき
0 | 1 | 2 | 3 | |
0 | 0 | 8 | 9 | 4 |
1 | 10 | 1 | 5 | 12 |
2 | 11 | 6 | 2 | 14 |
3 | 7 | 13 | 15 | 3 |
n = 5 のとき
0 | 1 | 2 | 3 | 4 | |
0 | 0 | 9 | 10 | 11 | 5 |
1 | 12 | 1 | 15 | 6 | 16 |
2 | 13 | 17 | 2 | 19 | 20 |
3 | 14 | 7 | 21 | 3 | 23 |
4 | 8 | 18 | 22 | 24 | 4 |
n = 6 のとき
0 | 1 | 2 | 3 | 4 | 5 | |
0 | 0 | 12 | 13 | 14 | 15 | 6 |
1 | 16 | 1 | 20 | 21 | 7 | 22 |
2 | 17 | 23 | 2 | 8 | 26 | 27 |
3 | 18 | 24 | 9 | 3 | 30 | 31 |
4 | 19 | 10 | 28 | 32 | 4 | 34 |
5 | 11 | 25 | 29 | 33 | 35 | 5 |
1次元であるセル位置番号gと2次元添え字(i,j)を1:1に対応させるにはどうしたらよいでしょうか。
i = iz(g) j = jz(g)としましょう。
かなり複雑ですが次のようにプログラムすると一般化できます。
(一般化の意味は、6次までに限定されず、例えば100次でも199次でも成り立つという意味です。)
奇数次の場合
Sub zahyouk()
For i = 0 To n * n - 1
If i < n Then
iz(i) = i
jz(i) = i
End If
If i >= n And i < 2 * n - 1 Then
iz(i) = i - n
jz(i) = 2 * n - i - 1
If iz(i) >= jz(i) Then
iz(i) = iz(i) + 1
jz(i) = jz(i) - 1
End If
End If
m = Int(n / 2)
For j = 1 To m
aj = -j * j + (4 * m + 1) * j + 1
If i >= aj And i < aj + n - 1 - j Then
iz(i) = j - 1
jz(i) = i - aj + j
If jz(i) >= n - j Then jz(i) = jz(i) + 1
End If
bj = -j * j + 4 * m * j + 2 * m + 1
If i >= bj And i < bj + n - 1 - j Then
iz(i) = i - bj + j
jz(i) = j - 1
If iz(i) >= n - j Then iz(i) = iz(i) + 1
End If
cj = -j * j + (2 * m + 3) * j + 3 * m * m + m - 1
If i >= cj And i < cj + m + 1 - j Then
iz(i) = m + j - 1
jz(i) = i - cj + m + j
End If
dj = -j * j + (2 * m + 2) * j + 3 * m * m + 2 * m
If i >= dj And i < dj + m + 1 + j Then
iz(i) = i - dj + m + j
jz(i) = m + j - 1
End If
Next
Next
End Sub
偶数次の場合
Sub zahyoug()
For i = 0 To n * n - 1
If i < n Then
iz(i) = i
jz(i) = i
End If
If i >= n And i < 2 * n Then
iz(i) = i - n
jz(i) = 2 * n - i - 1
End If
m = Int(n / 2)
w = m - 1
For j = 1 To m
aj = -j * j + (4 * w + 3) * j + 2
If i >= aj And i < aj + n - 1 - j Then
iz(i) = j - 1
jz(i) = i - aj + j
If jz(i) >= n - j Then jz(i) = jz(i) + 1
End If
Next
For j = 1 To m
bj = -j * j + (4 * w + 2) * j + 2 * w + 3
If i >= bj And i < bj + n - 1 - j Then
jz(i) = j - 1
iz(i) = i - bj + j
If iz(i) >= n - j Then iz(i) = iz(i) + 1
End If
Next
For j = 1 To m - 1
cj = -j * j + (3 + 2 * w) * j + 3 * w * w + 5 * w + 2
If i >= cj And i < cj + m - j Then
iz(i) = j + w
jz(i) = i - cj + m + j
End If
Next
For j = 1 To m - 1
dj = -j * j + (2 * w + 2) * j + 3 * w * w + 6 * w + 3
If i >= dj And i < dj + m - j Then
jz(i) = j + w
iz(i) = i - dj + m + j
End If
Next
Next
End Sub
今回は大変複雑なプログラムです。
階差数列の和をつかって、分析して以上のようにプログラムしたわけです。
実際、番号2次元添え字対応表プログラム
を実行してみると例えば10次では
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | |
0 | 0 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 11 |
1 | 30 | 1 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 12 | 46 |
2 | 31 | 47 | 2 | 55 | 56 | 57 | 58 | 59 | 13 | 60 | 61 |
3 | 32 | 48 | 62 | 3 | 69 | 70 | 71 | 14 | 72 | 73 | 74 |
4 | 33 | 49 | 63 | 75 | 4 | 81 | 15 | 82 | 83 | 84 | 85 |
5 | 34 | 50 | 64 | 76 | 86 | 5 | 91 | 92 | 93 | 94 | 95 |
6 | 35 | 51 | 65 | 77 | 16 | 96 | 6 | 101 | 102 | 103 | 104 |
7 | 36 | 52 | 66 | 17 | 87 | 97 | 105 | 7 | 109 | 110 | 111 |
8 | 37 | 53 | 18 | 78 | 88 | 98 | 106 | 112 | 8 | 115 | 116 |
9 | 38 | 19 | 67 | 79 | 89 | 99 | 107 | 113 | 117 | 9 | 119 |
10 | 20 | 54 | 68 | 80 | 90 | 100 | 108 | 114 | 118 | 120 | 10 |
となっていてgとi、jの関係に普遍性があることがわかります。
しかし、かなり難解なプログラムであることは認めざるを得ません。
次回で詳しく解説したいと思います。
また、表示のプログラムソースを示しておくと、
Sub hyouji()
Dim i As Integer
iti = iti + n + 1
For i = 0 To n * n - 1
Cells(iti + iz(i) + 2, 2 + jz(i)) = i
Next
For i = 0 To n - 1
Cells(iti + 1, i + 2).Select
With Selection.Font
.ColorIndex = 7
End With
Cells(iti + 1, i + 2) = i
Next
For i = 0 To n - 1
Cells(iti + i + 2, 1).Select
With Selection.Font
.ColorIndex = 3
End With
Cells(iti + i + 2, 1) = i
Next
Cells(2, 1).Select
End Sub
です。
Cells(iti + iz(i) + 2, 2 + jz(i)) = i
のitiについては後でまた説明しますが、
表示行位置調整のためのものです。
第3講第1話へ 第3講第3話へ