第3講 第2講の魔方陣を高速化しよう!
第3話 1次元gと2次元添え字(i,j)の関係−奇数の場合の解説
奇数の場合の例(19次)
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | |
0 | 0 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 19 |
1 | 54 | 1 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 20 | 86 |
2 | 55 | 87 | 2 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 21 | 116 | 117 |
3 | 56 | 88 | 118 | 3 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 22 | 144 | 145 | 146 |
4 | 57 | 89 | 119 | 147 | 4 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 23 | 170 | 171 | 172 | 173 |
5 | 58 | 90 | 120 | 148 | 174 | 5 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 24 | 194 | 195 | 196 | 197 | 198 |
6 | 59 | 91 | 121 | 149 | 175 | 199 | 6 | 211 | 212 | 213 | 214 | 215 | 25 | 216 | 217 | 218 | 219 | 220 | 221 |
7 | 60 | 92 | 122 | 150 | 176 | 200 | 222 | 7 | 233 | 234 | 235 | 26 | 236 | 237 | 238 | 239 | 240 | 241 | 242 |
8 | 61 | 93 | 123 | 151 | 177 | 201 | 223 | 243 | 8 | 253 | 27 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 |
9 | 62 | 94 | 124 | 152 | 178 | 202 | 224 | 244 | 262 | 9 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 |
10 | 63 | 95 | 125 | 153 | 179 | 203 | 225 | 245 | 28 | 280 | 10 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 |
11 | 64 | 96 | 126 | 154 | 180 | 204 | 226 | 29 | 263 | 281 | 297 | 11 | 305 | 306 | 307 | 308 | 309 | 310 | 311 |
12 | 65 | 97 | 127 | 155 | 181 | 205 | 30 | 246 | 264 | 282 | 298 | 312 | 12 | 319 | 320 | 321 | 322 | 323 | 324 |
13 | 66 | 98 | 128 | 156 | 182 | 31 | 227 | 247 | 265 | 283 | 299 | 313 | 325 | 13 | 331 | 332 | 333 | 334 | 335 |
14 | 67 | 99 | 129 | 157 | 32 | 206 | 228 | 248 | 266 | 284 | 300 | 314 | 326 | 336 | 14 | 341 | 342 | 343 | 344 |
15 | 68 | 100 | 130 | 33 | 183 | 207 | 229 | 249 | 267 | 285 | 301 | 315 | 327 | 337 | 345 | 15 | 349 | 350 | 351 |
16 | 69 | 101 | 34 | 158 | 184 | 208 | 230 | 250 | 268 | 286 | 302 | 316 | 328 | 338 | 346 | 352 | 16 | 355 | 356 |
17 | 70 | 35 | 131 | 159 | 185 | 209 | 231 | 251 | 269 | 287 | 303 | 317 | 329 | 339 | 347 | 353 | 357 | 17 | 359 |
18 | 36 | 102 | 132 | 160 | 186 | 210 | 232 | 252 | 270 | 288 | 304 | 318 | 330 | 340 | 348 | 354 | 358 | 360 | 18 |
以下の説明では、gは上の表の紺色の数字、
iz(g)はi(上の表の赤色の数字)、
jz(g)はj(上の表のピンク色の数字)を表していることに注意してください。
また、エクセルのプログラムソースでは
iz(i)=i(座標を作るプロシージャではgがiと表されているため。)などとなっていますが、
混乱を避けるためiz(g)=gなどと表記します。
さらに、n=19(19次を例にしていますので)を前提していることも忘れないでください。
If g < n Then
iz(g) = g
jz(g) = g
End If
If g >= n And g < 2 * n - 1 Then
iz(g) = g - n
jz(g) = 2 * n - g - 1
If iz(g) >= jz(g) Then
iz(g) = iz(g) + 1
jz(g) = jz(g) - 1
End If
End If
青の部分は明らかです。
g、i、jは一致しているからです。
iz(g) = g - nも自然です。
gから19を引けばiに一致することは表から明らかであるからです。
jz(g) = 2 * n - g - 1はわかりにくいかもしれませんが、
gが増えるたびにjが減っていくことに気がつけば、
気がつくのは容易ではないでしょうか。
例えば、g=26なら
jz(26)=2×19ー26−1=11です。
ほかも表と見比べながら一致することをご確認ください。
さて、
If iz(g) >= jz(g) Then
iz(g) = iz(g) + 1
jz(g) = jz(g) - 1
End If
はどういう意味でしょうか。
iz(g) = jz(g)とはg=28で
9 |
の位置を示しています。したがって、
iz(g) = iz(g) + 1
jz(g) = jz(g) - 1
がないとg=28がg=9と重なってしまいます。
iz(g) = iz(g) + 1
jz(g) = jz(g) - 1
はg=28が1つずれて
28 |
の位置に来るようにしているのです。
iz(g) > jz(g)
についても同様です。g=29以降をすべて1つずつずらしているのです。
問題は
m = Int(n / 2)
For j = 1 To m
aj = -j * j + (4 * m + 1) * j + 1
If g >= aj And g < aj + n - 1 - j Then
iz(g) = j - 1
jz(g) = g - aj + j
If jz(g) >= n - j Then jz(g) = jz(g) + 1
End If
bj = -j * j + 4 * m * j + 2 * m + 1
If g >= bj And g < bj + n - 1 - j Then
iz(g) = g - bj + j
jz(g) = j - 1
If iz(g) >= n - j Then iz(g) = iz(g) + 1
End If
cj = -j * j + (2 * m + 3) * j + 3 * m * m + m - 1
If g >= cj And g < cj + m + 1 - j Then
iz(g) = m + j - 1
jz(g) = g - cj + m + j
End If
dj = -j * j + (2 * m + 2) * j + 3 * m * m + 2 * m
If g >= dj And g < dj + m + 1 + j Then
iz(g) = g - dj + m + j
jz(g) = m + j - 1
End If
Next
の記述でしょう。
aj、bj、cj、djで始まるそれぞれの部分は、
順に水色、黄色、薄紫色、薄紺色に対応しています。
まずajすなわち水色から見ていきましょう。
赤色を付けた37,71,103,133,161,187,211,233,253は
aj = -j * j + (4 * m + 1) * j + 1において、
jが1,2,3,4,5,6,7,8,9の値をとる場合に相当します。
しかも、19次だけでなく奇数次ならすべて当てはまります。
例えば、17次ならm=8(m = Int(n / 2)なので)で
33,63,91,117,141,163,183,201となります。
つまり、aj = -j * j + (4 * m + 1) * j + 1は
次数にかかわらず普遍的(一般的)に成り立つわけです。
つまり、ajは次数に関わらず共通のjの2次関数になっているのです。
したがって、g >= aj And g < aj + n - 1 - jによって、
1行目なら37以上53以下
2行目なら71以上86以下
3行目なら103以上117以下
4行目なら133以上146以下
・
・
となり、
iz(g) = j - 1
は自然といえます。
for文はjを1から始めていますので1引いているのです。
jz(g) = g - aj + j
のjはjz(g)の始まりが1行進むごと右にずれているので、
それに対応するためです。
ではIf jz(g) >= n - j Then jz(g) = jz(g) + 1
の意味は何でしょうか。
これは逆対角線に重なるか、
それより右にあるときは右に1個ずらすという命令です。
これは例えば86が逆対角線上の20と重ならないようにしています。
逆対角線と重なるかそれより右にあるときは、
1個ずらさないと対角線を飛び越して入れるという原則に反してしまうからです。
ajの部分がわかればbj以降の理解も容易でしょう。
bjにおいては、
54,87,118,147,174,199,222,243,263が
bj = -j * j + 4 * m * j + 2 * m + 1
の式に従っているのです。つまりjの2次関数になっているのです。
If iz(g) >= n - j Then iz(g) = iz(g) + 1
も逆対角線を飛ぶように命令しているのです。
cjとdjでは逆対角線を横切る心配がないので、
if文に相当する部分はありません。
どうですか。
かなり難解に見えたソースの仕掛けが見えてきたのではないでしょうか。
第3講第2話へ 第3講第4話へ