第28講 細胞構成法による魔方陣の作成△
第16話 細胞構成法完成の解説その2
コード再掲
#pragma once
#include<stdlib.h>
int n;
int
a1[20][20],a2[20][20],a3[20][20],mah[20][20],p[20][20],cn1[20],cn2[20];
int x[400],y[400];
int s;
char
sbr[24][2][2];
char sb[2][2];
char sx[4],sy[4];
char
cn;
・
・
・
#pragma
endregion
private: System::Void button1_Click(System::Object^ sender,
System::EventArgs^ e)
{
label2->Text=L"";
DateTime^
hj=DateTime::Now;
n=int::Parse(textBox1->Text);
char
h=1;
if(n<3 || n>14 ||
n%2==0){
label2->Text=L"TextBoxには3以上11以下の奇数\r\nを入力し再度実行ボタンを\r\n押して下さい。";
h=0;
}
if(h==1){
s=0;
if(n%2==1)g1(n);
if(n%2==0)g2(n);
syokika();
cn=0;
zhy();
sbs(0);
sbg(0);
array<String^>^
w=gcnew array<String^>(15);
int
i;
w[9]=(2*n).ToString();w[10]=L"次";w[11]=L"魔";w[12]=L"方";w[13]=L"陣";w[14]=s.ToString();
for(i=0;i<8;i++)w[i]=L"";
dataGridView1->Rows->Add(w);
DateTime^
ow=DateTime::Now;
TimeSpan
sa=ow->Subtract(*hj);
w[9]=L"時";w[10]=L"間";w[11]=L"計";w[12]=L"則";w[13]=L":";w[14]=(sa.TotalSeconds).ToString();
for(i=0;i<9;i++)w[i]=L"";
dataGridView1->Rows->Add(w);
}
}
・
・
・
void
sbg(int g){
if(s==200)return;
int
i,j,k,h,w,ii,iii;
ii=rand()%24;
for(i=0;i<24;i++){
iii=(ii+i)%24;
for(j=0;j<2;j++){
for(k=0;k<2;k++){
a3[2*y[g]+j][2*x[g]+k]=sbr[iii][j][k];
}
}
h=1;
if(g==n-1){
w=0;
for(j=0;j<2*n;j++){
w+=a3[j][j];
}
if(w!=5*n)h=0;
}
if(h==1){
if(g==2*n-2){
w=0;
for(j=0;j<2*n;j++){
w+=a3[j][2*n-1-j];
}
if(w!=5*n)h=0;
}
}
if(h==1){
if(y[g]==0
&&
x[g]==n-2){
for(j=0;j<2;j++){
w=0;
for(k=0;k<2*n;k++){
w+=a3[2*y[g]+j][k];
}
if(w!=5*n){
h=0;
break;
}
}
}
}
if(h==1){
if(x[g]==0
&&
y[g]==n-2){
for(j=0;j<2;j++){
w=0;
for(k=0;k<2*n;k++){
w+=a3[k][2*x[g]+j];
}
if(w!=5*n){
h=0;
break;
}
}
}
}
if(h==1){
if(g>2*n-2
&&
x[g]==n-1){
for(j=0;j<2;j++){
w=0;
for(k=0;k<2*n;k++){
w+=a3[2*y[g]+j][k];
}
if(w!=5*n){
h=0;
break;
}
}
}
}
if(h==1){
if(g>2*n-2
&&
y[g]==n-1){
for(j=0;j<2;j++){
w=0;
for(k=0;k<2*n;k++){
w+=a3[k][2*x[g]+j];
}
if(w!=5*n){
h=0;
break;
}
}
}
}
if(h==1){
if(g==n*n-2){
for(j=0;j<2;j++){
w=0;
for(k=0;k<2*n;k++){
w+=a3[k][2*x[g]+j];
}
if(w!=5*n){
h=0;
break;
}
}
}
}
if(h==1){
if(g==n*n-1){
for(j=0;j<2;j++){
w=0;
for(k=0;k<2*n;k++){
w+=a3[2*y[g]+j][k];
}
if(w!=5*n){
h=0;
break;
}
}
}
}
if(h==1){
if(g+1<n*n){
sbg(g+1);
}
else{
if(n!=3 )f0(0);
if(n==3)f1(0);
}
}
}
}
・
・
・
void f00(int
g){
if(s==200)return;
・
・
・
if(h==1){
if(g+1<n){
f00(g+1);
}
else{
for(j=1;j<n;j++){
for(k=0;k<n;k++){
l=(3*j+k)%n;
a2[j][l]=a2[0][k];
}
}
for(j=0;j<n;j++){
for(k=0;k<n;k++){
for(l=0;l<2;l++){
for(o=0;o<2;o++){
mah[2*j+l][2*k+o]=4*(n*a1[j][k]+a2[j][k])+a3[2*j+l][2*k+o];
}
}
}
}
array<String^>^
w=gcnew
array<String^>(15);
for(j=0;j<2*n;j++){
for(k=0;k<2*n;k++){
w[k]=(mah[j][k]).ToString();
}
dataGridView1->Rows->Add(w);
}
for(j=0;j<15;j++)w[j]=L"";
dataGridView1->Rows->Add(w);
s++;
if(s==200)return;
}
}
}
}
・
・
・
void
f2(int
g){
if(s==200)return;
・
・
・
if(g<n*n-1){
f2(g+1);
}
else{
for(j=0;j<n;j++){
for(k=0;k<n;k++){
for(l=0;l<2;l++){
for(o=0;o<2;o++){
mah[2*j+l][2*k+o]=4*(n*a1[j][k]+a2[j][k])+a3[2*j+l][2*k+o];
}
}
}
}
array<String^>^
w=gcnew
array<String^>(15);
for(j=0;j<2*n;j++){
for(k=0;k<2*n;k++){
w[k]=(mah[j][k]).ToString();
}
dataGridView1->Rows->Add(w);
}
for(j=0;j<15;j++)w[j]=L"";
dataGridView1->Rows->Add(w);
s++;
if(s==200)return;
}
・
・
・
基本発想は何でしょうか。
実は、奇数方陣と細胞合成の合体です。
本当は奇数方陣との組み合わせである必要はありません。
偶数方陣との組み合わせでもよかったのですが、
今回は、3次5次7次に限定しただけです。
次講では、限定を外して普遍的な形にもっていきます。
さらに、次次講ではマルチスレッド化してより高速化を図ります。
さて、奇数方陣と細胞合成の組み合わせとは具体的になんでしょうか。
8 | 1 | 6 |
3 | 5 | 7 |
4 | 9 | 2 |
3 | 4 | 3 | 1 | 3 | 1 |
1 | 2 | 4 | 2 | 4 | 2 |
3 | 2 | 3 | 4 | 1 | 2 |
1 | 4 | 1 | 2 | 4 | 3 |
3 | 1 | 3 | 4 | 1 | 3 |
4 | 2 | 1 | 2 | 2 | 4 |
この2つの合体です。
31 | 32 | 3 | 1 | 23 | 21 |
29 | 30 | 4 | 2 | 24 | 22 |
11 | 10 | 19 | 20 | 25 | 26 |
9 | 12 | 17 | 18 | 28 | 27 |
15 | 13 | 35 | 36 | 5 | 7 |
16 | 14 | 33 | 34 | 6 | 8 |
どのように合体しているのでしょうか。
7 |
7
1 | 2 |
4 | 3 |
を例に説明しましょう。
次のように計算しています。
7 |
から1を引いて4倍してそれに
1 | 2 |
4 | 3 |
を加えています。
25 | 26 |
28 | 27 |
つまり、
8 | 1 | 6 |
3 | 5 | 7 |
4 | 9 | 2 |
3 | 4 | 3 | 1 | 3 | 1 |
1 | 2 | 4 | 2 | 4 | 2 |
3 | 2 | 3 | 4 | 1 | 2 |
1 | 4 | 1 | 2 | 4 | 3 |
3 | 1 | 3 | 4 | 1 | 3 |
4 | 2 | 1 | 2 | 2 | 4 |
上から1引いて4をかけ、それに下を足しているのです。
31 | 32 | 3 | 1 | 23 | 21 |
29 | 30 | 4 | 2 | 24 | 22 |
11 | 10 | 19 | 20 | 25 | 26 |
9 | 12 | 17 | 18 | 28 | 27 |
15 | 13 | 35 | 36 | 5 | 7 |
16 | 14 | 33 | 34 | 6 | 8 |
4をかける理由は、4飛びにするためです。
3次魔方陣と細胞合成の合体による3次魔方陣の6次化です。
各数字は、(7-1)×4+1のように計算されていますので、
36個の数字は次のように構成されてします。
(8-1)×4+3、(8-1)×4+4、(1-1)×4+3、(1-1)×4+1、(6-1)×4+3、(6-1)×4+1
(8-1)×4+1、(8-1)×4+2、(1-1)×4+4、(1-1)×4+2、(6-1)×4+4、(6-1)×4+2
(3-1)×4+3、(3-1)×4+2、(5-1)×4+3、(5-1)×4+4、(7-1)×4+1、(7-1)×4+2
(3-1)×4+1、(3-1)×4+4、(5-1)×4+1、(5-1)×4+2、(7-1)×4+4、(7-1)×4+3
(4-1)×4+3、(4-1)×4+1、(9-1)×4+3、(9-1)×4+4、(2-1)×4+1、(2-1)×4+3
(4-1)×4+4、(4-1)×4+2、(9-1)×4+1、(9-1)×4+2、(2-1)×4+2、(2-1)×4+4
これのすべての行合計・列合計・対角線合計が一致することは当然です。
例えば1行目と3行目の合計は、
((8-1)×4+3)+((8-1)×4+4)+((1-1)×4+3)+((1-1)×4+1)+((6-1)×4+3)+((6-1)×4+1)
((3-1)×4+3)+((3-1)×4+2)+((5-1)×4+3)+((5-1)×4+4)+((7-1)×4+1)+((7-1)×4+2)
ですが、8・1・6と3・5・7の合計、3・4・3・1・3・1と3・2・3・4・1・2の合計のそれぞれが一致するのは当然です。
8 | 1 | 6 |
3 | 5 | 7 |
4 | 9 | 2 |
3 | 4 | 3 | 1 | 3 | 1 |
1 | 2 | 4 | 2 | 4 | 2 |
3 | 2 | 3 | 4 | 1 | 2 |
1 | 4 | 1 | 2 | 4 | 3 |
3 | 1 | 3 | 4 | 1 | 3 |
4 | 2 | 1 | 2 | 2 | 4 |
それらは、もともと3次魔方陣と細胞合成の各数字だったからです。
8・1・6と3・5・7の合計、3・4・3・1・3・1と3・2・3・4・1・2の合計のそれぞれが一致するですから、1行目と3行目の合計
((8-1)×4+3)+((8-1)×4+4)+((1-1)×4+3)+((1-1)×4+1)+((6-1)×4+3)+((6-1)×4+1)
((3-1)×4+3)+((3-1)×4+2)+((5-1)×4+3)+((5-1)×4+4)+((7-1)×4+1)+((7-1)×4+2)
も当然一致します。
((8-1)×4)+((8-1)×4)+((1-1)×4)+((1-1)×4)+((6-1)×4)+((6-1)×4)
((3-1)×4)+((3-1)×4)+((5-1)×4)+((5-1)×4)+((7-1)×4)+((7-1)×4)
と
3+4+3+1+3+1
3+2+3+4+1+2
に分解すれば当然だと言うことがわかります。
どうでしょうか。
今回は、コード解説と言うより細胞構成法の説明になりました。
この説明とコードを符合させながら、コードをお読みになれば理解できると思います。
この講は大部大きくなってしまいました。まだ、細胞構成法の講義は続きますが、講をいったん閉めます。
第15話へ 第29講第1話へ
VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual
Basic入門基礎講座