最終講 卒業研究と卒業試験

第3話 課題2 9次ラテン方陣の作成

前話の課題の解答例
#pragma once
int a[3][3];
int x[9],y[9];
int s;
namespace 順列方陣 {

  using namespace System;  
        ・
        ・
        ・
#pragma endregion
  private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
           s=0;
           g();
           f(0);
           
array<String^>^ w=gcnew array<String^>(14);
           w[8]=L"順";w[9]=L"列";w[10]=L"総";w[11]=L"数";w[12]=L":";w[13]=s.ToString();
           dataGridView1->Rows->Add(w);

        }
        void g(){
           char i;
           for(i=0;i<9;i++){
             x[i]=i%3;
             y[i]=i/3;
           }
        }
        void f(char g){
           if(s==100)return;  'すべて計算させるとかなり時間がかかるので100個で止めている。
           int i,j,k,h,
sa,ss;
           for(i=0;i<9;i++){
             a[y[g]][x[g]]=i+1;
             h=1;
              if(g>0){
               for(j=0;j<g;j++){
                 if(a[y[g]][x[g]]==a[y[j]][x[j]]){
                   h=0;
                   break;
                 }
               }
             }

        void f(char g){
           if(s==100)return;  'すべて計算させるとかなり時間がかかるので100個で止めている。
           int i,j,k,h,
sa,ss;
           for(i=0;i<9;i++){
             a[y[g]][x[g]]=i+1;
             h=1;
              if(g>0){
               for(j=0;j<g;j++){
                 if(a[y[g]][x[g]]==a[y[j]][x[j]]){
                   h=0;
                   break;
                 }
               }
             }

             if(h==1){
               if(g+1<9){
                 f(g+1);
               }
              else{
                sa=s%3;
                ss=s/3;

                for(j=0;j<3;j++){
                  
if(sa==0)dataGridView1->Rows->Add();
                  for(k=0;k<3;k++){
                    dataGridView1[
k+4*sa,j+4*ss]->Value=a[j][k];
                  }
                }
                
if(sa==0)dataGridView1->Rows->Add();

                 s++;
              }
            }
           }
        }

  };
}

さらに、改良して計算時間が計測できるように変更したいと思います。
  private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
           DateTime hj=DateTime::Now;
           s=0;
           g();
           f(0);
           
array<String^>^ w=gcnew array<String^>(14);
           w[8]=L"順";w[9]=L"列";w[10]=L"総";w[11]=L"数";w[12]=L":";w[13]=s.ToString();
           dataGridView1->Rows->Add(w);

          
DateTime ow=DateTime::Now;
           TimeSpan sa=ow-hj;
           w[8]=L"時";w[9]=L"間";w[10]=L"計";w[11]=L"則";w[12]=L":";w[13]=(sa.TotalSeconds).ToString();
           dataGridView1->Rows->Add(w);

        }

hjowは現在の時間を取得するための変数です。時間を取得するための型がDateTimeであると理解されてください。
hjで始まりの現在時刻、owで終わりの現在時刻を取得しています。
DateTime::Nowは現在の時間です。
saは時刻差を計算するための変数です。時刻差を計算する変数の型は、TimeSpanなのです。
また、sa.TotalSecondsは時刻差を秒に変換するためのものです。
入門



さて、9次ラテン方陣の解答例を示しましょう。
#pragma once
int a[9][9];
int x[81],y[81];
int s;
namespace 順列方陣 {

  using namespace System;  
        ・
        ・
        ・
#pragma endregion
  private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
           DateTime hj=DateTime::Now;
           s=0;
           g();
           f(0);
           array<String^>^ w=gcnew array<String^>(14);
           w[8]=L"順";w[9]=L"列";w[10]=L"総";w[11]=L"数";w[12]=L":";w[13]=s.ToString();
           dataGridView1->Rows->Add(w);
           DateTime ow=DateTime::Now;
           TimeSpan sa=ow-hj;
           w[8]=L"時";w[9]=L"間";w[10]=L"計";w[11]=L"則";w[12]=L":";w[13]=(sa.TotalSeconds).ToString();
           dataGridView1->Rows->Add(w);
        }
        void g(){
           char i;
           for(i=0;i<
81;i++){
             x[i]=i%
9;
             y[i]=i/
9;
           }
        }
        void f(char g){
           if(s==100)return;  'すべて計算させるとかなり時間がかかるので100個で止めている。
           int i,j,k,h;
           for(i=0;i<
9;i++){
             a[y[g]][x[g]]=i+1;
             h=1;
             
if(y[g]>0){
               for(j=0;j<y[g];j++){
                 if(a[y[g]][x[g]]==a[j][x[g]]){
                   h=0;
                   break;
                 }
               }
             }
             if(h==1){
               if(x[g]>0){
                 for(j=0;j<x[g];j++){
                   if(a[y[g]][x[g]]==a[y[g]][j]){
                     h=0;
                     break;
                   }
                 }
               }
             }


             if(h==1){
               if(g+1<
81){
                 f(g+1);
               }
              else{
                for(j=0;j<
9;j++){
                  dataGridView1->Rows->Add();
                  for(k=0;k<
9;k++){
                    dataGridView1[
k,j+10*s]->Value=a[j][k];
                  }
                }
                dataGridView1->Rows->Add();

                s++;
              }
            }
           }
        }

  };
}
実行例
初心者
変更点は、で示されています。配列の次数を変更し、
              if(g>0){
               for(j=0;j<g;j++){
                 if(a[y[g]][x[g]]==a[y[j]][x[j]]){
                   h=0;
                   break;
                 }
               }
             }

              if(y[g]>0){
               for(j=0;j<y[g];j++){
                 if(a[y[g]][x[g]]==a[j][x[g]]){
                   h=0;
                   break;
                 }
               }
             }
             if(h==1){
               if(x[g]>0){
                 for(j=0;j<x[g];j++){
                   if(a[y[g]][x[g]]==a[y[g]][j]){
                     h=0;
                     break;
                   }
                 }
               }
             }

と変わっています。課題1では、行列の中に同じ数字が入ってはいけないという条件だったのに対して、
ラテン方陣では、行または列の中のみに同じ数字が入ってはいけないという条件だからです。
行または列に同じ数字が入らなければ、行列の中に同じ数字が入ってもよいのです。
初歩はじめての
前半
              if(y[g]>0){
               for(j=0;j<y[g];j++){
                 if(a[y[g]][x[g]]==a[j][x[g]]){
                   h=0;
                   break;
                 }
               }
             }
で列基礎のチェック

後半
             if(h==1){
               if(x[g]>0){
                 for(j=0;j<x[g];j++){
                   if(a[y[g]][x[g]]==a[y[g]][j]){
                     h=0;
                     break;
                   }
                 }
               }
             }

で行入門のチェックをしています。
同じものがあるとh = 0 となり、
             if(h==1){
               if(g+1<
81){
                 f(g+1);
               }
              else{
                for(j=0;j<9;j++){
                  dataGridView1->Rows->Add();
                  for(k=0;k<9;k++){
                    dataGridView1[
k,j+10*s]->Value=a[j][k];
                  }
                }
                dataGridView1->Rows->Add();

                s++;
              }
            }
が実行ず、ループが次に進むようになっています。
尚、皆さんfor(i=0;i<9;i++)の9if(g+1<81)の81に注意されてください。
行や列に入る数字(セルの内容)は1から9まで(a[y[g]][x[g]]=i+1; +1があるので0から8は1から9までとなる)
であるのに対して、セル番号は0から80までです。
繰り返しますが、セル番号(セルのラベル)とセルの内容(セルに入る1から9までの数字)は明確に区別しないといけません。
明瞭に区別していないと、プログラムは訳のわからないものとなります。
初心者はじめての



さて、皆さん課題3
課題2に条件
C ブロックの数字が重複してはならない。
を付け加えてください。
に挑戦しましょう。


第2話へ 第4話へ


025


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



数学研究室に戻る