第19講 魔方陣汎用的生成プログラムVer.2
第8話 シード及び飛び値最適化実験コード

シード及び飛び値最適化実験コード
class x1{
  public static int[] x=new int[100];
  public static int[] y=new int[100];
  public static int[][] m=new int[20][20];
  public static int n,cn;
  static double hj,ow;
  static int t=1;
  static long s;
  static double mn;
  public static void main(String args[]) throws IOException {
    //BufferedReader a = new BufferedReader(new InputStreamReader(System.in));
    //System.out.println("何次魔方陣を生成させますか。");
    //System.out.print("n=");
    //n=Integer.parseInt(a.readLine());
    n=5;
    z();
    int i;
    for(s=0;s<50;s++){
      System.out.println(s);
      if(n==5){
        for(i=0;i<7;i++){
          mn=10000;
          if(i==0){t=3;System.out.println(" "+t);}
          if(i==1){t=7;System.out.println(" "+t);}
          if(i==2){t=11;System.out.println(" "+t);}
          if(i==3){t=13;System.out.println(" "+t);}
          if(i==4){t=17;System.out.println(" "+t);}
          if(i==5){t=19;System.out.println(" "+t);}
          if(i==6){t=23;System.out.println(" "+t);}
          hj = System.currentTimeMillis();
          cn=0;
          f(0);
        }
      }
      if(n==6){
        for(i=0;i<8;i++){
          mn=10000;
          if(i==0){t=5;System.out.println(" "+t);}
          if(i==1){t=7;System.out.println(" "+t);}
          if(i==2){t=11;System.out.println(" "+t);}
          if(i==3){t=13;System.out.println(" "+t);}
          if(i==4){t=17;System.out.println(" "+t);}
          if(i==5){t=19;System.out.println(" "+t);}
          if(i==6){t=23;System.out.println(" "+t);}
          if(i==7){t=29;System.out.println(" "+t);}
          if(i==8){t=31;System.out.println(" "+t);}
          hj = System.currentTimeMillis();
          cn=0;
          f(0);
        }
      }
    }
    /*
    ow = System.currentTimeMillis();
    System.out.println();
    System.out.println(n+"次魔方陣が"+cn+"個できました。");
    System.out.println("魔方陣の探索にかかった時間は"+(ow-hj)/1000+"秒です。");
    */
  }
  public static void z(){
    int i,j,p;
    int[][] a=new int[20][20];
    for(i=0;i<n;i++){
      for(j=0;j<n;j++){
        a[i][j]=n*n;
      }
    }
    for(i=0;i<n;i++){
      a[i][i]=i;
    }
    p=n;
    for(i=0;i<n;i++){
      if(a[i][n-1-i]==n*n){
        a[i][n-1-i]=p;
        p++;
      }
    }
    for(i=0;i<n;i++){
      for(j=0;j<n;j++){
        if(a[i][j]==n*n){
          a[i][j]=p;
          p++;
        }
      }
    }
    for(i=0;i<n;i++){
      for(j=0;j<n;j++){
        y[a[i][j]]=i;
        x[a[i][j]]=j;
      }
    }
  }
  /*
  public static void h(){
    int i,j;
    for(i=0;i<n*n;i++){
      m[y[i]][x[i]]=i;
    }
    for(i=0;i<n;i++){
      for(j=0;j<n;j++){
        if(m[i][j]<10){
          System.out.print(" "+m[i][j]+" ");
        }
        else{
          System.out.print(m[i][j]+" ");
        }
      }
      System.out.println();
    }
  }
  */
  public static void f(int g){
    if((ow-hj)/1000>mn)return;
    int i,j,k,h,w,ii,iii;

    Random r = new Random(s);

    ii=(int)(r.nextFloat()*(n*n));

    for(i=1;i<n*n+1;i++){
      h=1;
      iii=(t*i+ii)%(n*n)+1;
      m[y[g]][x[g]]=iii;
      for(j=0;j<g;j++){
        if(m[y[g]][x[g]]==m[y[j]][x[j]]){
          h=0;
        }
      }
      if(h==1){
        if(y[g]==n-1 && x[g]==n-1){
          w=0;
          for(j=0;j<n;j++){
            w+=m[j][j];
          }
          if(w!=n*(n*n+1)/2)h=0;
        }
      }
      if(h==1){
        if(y[g]==n-1 && x[g]==0){
          w=0;
          for(j=0;j<n;j++){
            w+=m[j][n-1-j];
          }
          if(w!=n*(n*n+1)/2)h=0;
        }
      }
      if(h==1){
        if(y[g]==0 && x[g]==n-2){
          w=0;
          for(j=0;j<n;j++){
            w+=m[y[g]][j];
          }
          if(w!=n*(n*n+1)/2)h=0;
        }
      }
      if(h==1){
        if(x[g]==0 && y[g]==n-2){
          w=0;
          for(j=0;j<n;j++){
            w+=m[j][x[g]];
          }
          if(w!=n*(n*n+1)/2)h=0;
        }
      }
      if(h==1){
        if(y[g]>0 && y[g]<n-1 && x[g]==n-1){
          w=0;
          for(j=0;j<n;j++){
            w+=m[y[g]][j];
          }
          if(w!=n*(n*n+1)/2)h=0;
        }
      }
      if(h==1){
        if(x[g]>0 && x[g]<n-1 && y[g]==n-1){
          w=0;
          for(j=0;j<n;j++){
            w+=m[j][x[g]];
          }
          if(w!=n*(n*n+1)/2)h=0;
        }
      }
      if(h==1){
        if(g+1<n*n){
          f(g+1);
          if(cn>4)return;
          ow = System.currentTimeMillis();
          if((ow-hj)/1000>mn)return;
        }
        else{
          cn++;
          /*
          for(j=0;j<n;j++){
            for(k=0;k<n;k++){
              if(m[j][k]<10){
                System.out.print(" "+m[j][k]+" ");
              }
              else{
                System.out.print(m[j][k]+" ");
              }
            }
            System.out.println();
          }
          System.out.println();
          */
          if(cn>2){
            ow = System.currentTimeMillis();
            if(mn>(ow-hj)){
              mn=ow-hj;
              System.out.println(" s="+s+" t="+t+" "+" cn="+cn+" "+(ow-hj)/1000+"秒です。");
            }
            return;
          }
        }
      }
    }
  }
}
実行画面例
入門

途中経過をみるため
      System.out.println(s);
          if(i==0){t=3;System.out.println(" "+t);}
としてありますが、実際にはピンクの部分と
        for(i=0;i<7;i++){
          mn=10000;
の部分は削り、
for(s=0;s<50;s++){

    for(s=0;s<500;s++){
で実験しました。
ただし、大変時間がかかりますので、上限については皆さんが工夫してください。

さて、次話では私が末項確定法と名付けているVer.3に進化させます。
10倍から100倍程度になりますが、Ver.3の段階では対応は6次魔方陣間です。
しかし、1個あたり5次なら0.0085秒、6次なら0.9853秒という驚異的な結果を示します。

さらに、私が一般種法と名付けているVer.4になるとVer.3比で1万倍から数千万倍のスピードを実現し、
14次魔方陣まで作れるようになります。


第7話へ 第20講第1話へ

戻る

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

初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第1部
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第2部
初心者のための VC++による C言語 入門 C++ 入門 基礎から応用まで第3部