第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個の数字は次のように構成されてします。
-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+
-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+
-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+
-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+
-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+
-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+、(-1)×4+
これのすべての行合計・列合計・対角線合計が一致することは当然です。
例えば1行目と3行目の合計は、
((-1)×4+)+((-1)×4+)+((-1)×4+)+((-1)×4+)+((-1)×4+)+((-1)×4+
((
-1)×4+)+((-1)×4+)+((-1)×4+)+((-1)×4+)+((-1)×4+)+((-1)×4+
ですが、
8・1・63・5・7の合計、3・4・3・1・3・13・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・63・5・7の合計、3・4・3・1・3・13・2・3・4・1・2の合計のそれぞれが一致するですから、1行目と3行目の合計
((-1)×4+)+((-1)×4+)+((-1)×4+)+((-1)×4+)+((-1)×4+)+((-1)×4+
((
-1)×4+)+((-1)×4+)+((-1)×4+)+((-1)×4+)+((-1)×4+)+((-1)×4+
も当然一致します。
((-1)×4)+((-1)×4)+((-1)×4)+((-1)×4)+((-1)×4)+((-1)×4
((
-1)×4)+((-1)×4)+((-1)×4)+((-1)×4)+((-1)×4)+((-1)×4)



に分解すれば当然だと言うことがわかります。

どうでしょうか。
今回は、コード解説と言うより細胞構成法の説明になりました。
この説明とコードを符合させながら、コードをお読みになれば理解できると思います。

この講は大部大きくなってしまいました。まだ、細胞構成法の講義は続きますが、講をいったん閉めます。


第15話へ
第29講第1話へ

戻る

VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座