マルチスレッド版数独自動生成ソフトC++コードを題材とする超初心者のためのVisual Studio C++講義
第14章 一般種法による超超高速魔方陣自動生成
第4話 商生成コードのトレースその1

コード主要部分再掲
void tanez(size_t p, size_t s, size_t 商[n][n],size_t 前半回数[th][n]) {//一般種商生成関数
//商解析
size_t 始め = p / n;
for (size_t i = 0; i < n; i++) {
size_t h;
size_t Y;
Y = (始め + i) % n;
商[y[s]][x[s]] = Y;
h = 1;
if (前半回数[p][Y] >= n)h = 0;
前半回数[p][Y]++;
size_t gk;
if (y[s] == n - 1 && x[s] == n - 1) {
gk = 0;
for (size_t j = 0; j < n; j++)gk += 商[j][j];
if (gk != ig)h = 0;
}
if (継続 == 0)return;
if (h == 1) {
if (y[s] == n - 1 && x[s] == 0) {
gk = 0;
for (size_t j = 0; j < n; j++)gk += 商[j][n - 1 - j];
if (gk != ig)h = 0;
}
}
if (継続 == 0)return;
if (h == 1) {
if (y[s] == 0 && x[s] == n - 2) {
gk = 0;
for (size_t j = 0; j < n; j++)gk += 商[y[s]][j];
if (gk != ig)h = 0;
}
}
if (継続 == 0)return;
if (h == 1) {
if (y[s] > 0 && y[s] < n - 1 && x[s] == n - 1) {
gk = 0;
for (size_t j = 0; j < n; j++)gk += 商[y[s]][j];
if (gk != ig)h = 0;
}
}
if (h == 1) {
if (y[s] == n - 2 && x[s] == 0) {
gk = 0;
for (size_t j = 0; j < n; j++)gk += 商[j][x[s]];
if (gk != ig)h = 0;
}
}
if (継続 == 0)return;
if (h == 1) {
if (y[s] == n - 2 && x[s] == n - 1) {
gk = 0;
for (size_t j = 0; j < n; j++)gk += 商[j][x[s]];
if (gk != ig)h = 0;
}
}
if (継続 == 0)return;
if (h == 1) {
if (y[s] == n - 1 && x[s] > 0 && x[s] < n - 1) {
gk = 0;
for (size_t j = 0; j < n; j++)gk += 商[j][x[s]];
if (gk != ig)h = 0;
}
}
if (継続 == 0)return;
if (h == 1) {
if (y[s] == n - 1 && x[s] == n - 2) {
gk = 0;
for (size_t j = 0; j < n; j++)gk += 商[y[s]][j];
if (gk != ig)h = 0;
}
}
if (h == 1) {
if (s + 1 < th) {
tanez(p, s + 1, 商, 前半回数);
if (継続 == 0)return;
}
else {
for (size_t j = 0; j < n; j++) {
for (size_t k = 0; k < n; k++) {
商累積[cn][j][k] = 商[j][k];
}
}
InterlockedIncrement((volatile LONG*)&cn);
if (cn == ts) {
継続 = 0;
return;
}
}
}
前半回数[p][Y]--;
if (継続 == 0)return;
}
}
ではトレースを行っていきます。
長くなりますが、どうか1行1行確認しながらお読みください。
size_t 始め = p / n;
は種余り生成コードでは
size_t 始め = p % n;
となっています。
合成式は n * Y + X + 1となりますので、
n * (p / n) + p % n + 1 = p + 1
となります。
p = 0 のとき
n * (p / n) + p % n + 1 = 1
p = 1 のとき
n * (p / n) + p % n + 1 = 2
・
・
・
n * (p / n) + p % n + 1 = 36
ですから、座標(0,0)の値をスレッド毎に1,2,3,・・・,36の値を与え
魔方陣の最初に入力される値がスレッド毎に異なるようになっているわけです。

マルチスレッドなので綺麗に1,2,3,・・・,36とはなっていませんが、
座標(0,0)つまり始まりが異なっていることが実行画面から伝わってきます。
今これを書いて、商の重複があって合成された魔方陣に重複がないのは、
直交条件×始まりの数
にあることに気が付きました。

始まりの数が同じであっても同一の魔方陣になっていないことが、
観察されます。
青い囲いを見れば異なっていることは明らかです。
直交条件×始まりの数
2つの要因によって1万個生成しても同一魔方陣になっていないことがわかります。
重複検査が正しいことは生成AIであるCopilotが保証していますので確実です。
第14章第3話へ 第14章5話へ
本講義トップへ