数的推理の魔方陣の問題をJavaで解いてみた。

 数的推理の魔方陣の問題Javaで解いてみました。(^_^;
 縦横の和、斜めの和、四隅の和のが34になる性質だけを使って解いてみました。

+--+--+--+--+
|  | 9| 5|  |
+--+--+--+--+
|15|  |10|  |
+--+--+--+--+
|  |  |  |  |
+--+--+--+--+
| 1|  |  |  |
+--+--+--+--+

●MagicSquare4x4.java

/*
 * MagicSquare4x4.java
 * 
 * m                | p
 * [ 0][ 1][ 2][ 3] | [ 0]  9   5 [ *]
 * [ 4][ 5][ 6][ 7] |  15 [ 1] 10 [ *]
 * [ 8][ 9][10][11] | [ *][ *][ *][ *]
 * [12][13][14][15] |   1 [ *][ *][ *]
 *
 * 変数は、 2個
 * [ *]は、残差で求める
 * 
 */

class MagicSquare4x4 {
    static void swap(int[] s, int i, int j) {
        int t = s[i]; s[i] = s[j]; s[j] = t;
    }
    
    static boolean next_perm(int[] p, int n, int r) {
        int i, j, k;
        if(r <= 0 || n < r) return(false);
        for(i = r + 1; i <= n-1; i++)
            for(j = i; j >= r + 1 && p[j-1] < p[j]; j--)
                swap(p,j,j-1);
        for(i = n - 1; i > 0 && p[i-1] >= p[i]; i--);
        if(i==0) return(false);
        for(j = n - 1; j > i && p[i-1] >= p[j]; j--);
        swap(p,j,i-1);
        for(k = 0; k <= (n-i-1)/2; k++)
            swap(p,i+k,n-k-1);
        return(true);
    }
    
    // 残差を求めるメソッド
    static int Rem(int a, int b, int c) {
        return(34-a-b-c);
    }
    
    static int N=16;
    // 1〜Nまでちゃんと揃っているか調べるメソッド
    static boolean checkAllNum(int[] x) {
        int i,j;
        for(i=1;i<=N; i++){
            for(j=0; j< N; j++)
                if(x[j]==i) break;
            if(j==N) return(false);
        }   
        return(true);
    }
    
    static void disp(int c, int[] p) {  // 表示
        System.out.printf("[%d]\n",c);      
        System.out.printf("%3d%3d%3d%3d\n",p[ 0],p[ 1],p[ 2],p[ 3]);
        System.out.printf("%3d%3d%3d%3d\n",p[ 4],p[ 5],p[ 6],p[ 7]);
        System.out.printf("%3d%3d%3d%3d\n",p[ 8],p[ 9],p[10],p[11]);
        System.out.printf("%3d%3d%3d%3d\n",p[12],p[13],p[14],p[15]);
        System.out.println();
    }
    
    public static void main(String[] args) {
        int[] p={2,3,4,6,7,8,11,12,13,14,16};   // 順列生成用
        int[] m=new int[16];                    // 盤面用
        int c=0;
        long tm=System.nanoTime();      // Timer Start
        
        m[ 1]= 9; m[ 2]= 5;
        m[ 4]=15; m[ 6]=10;
        m[12]= 1;
        do{
            m[ 0]=p[ 0];
            m[ 5]=p[ 1];
            if((m[ 3]=Rem(m[ 0],m[ 1],m[ 2]))<1) continue;  // 1行目の和
            if((m[ 7]=Rem(m[ 4],m[ 5],m[ 6]))<1) continue;  // 2行目の和
            if((m[ 8]=Rem(m[ 0],m[ 4],m[12]))<1) continue;  // 1列目の和
            if((m[ 9]=Rem(m[ 3],m[ 6],m[12]))<1) continue;  // 斜め(/)の和
            if((m[13]=Rem(m[ 1],m[ 5],m[ 9]))<1) continue;  // 2列目の和
            if((m[15]=Rem(m[ 0],m[ 3],m[12]))<1) continue;  // 四隅の和
            if((m[11]=Rem(m[ 3],m[ 7],m[15]))<1) continue;  // 4列目の和
            if((m[14]=Rem(m[12],m[13],m[15]))<1) continue;  // 4行目の和
            if((m[10]=Rem(m[ 8],m[ 9],m[11]))<1) continue;  // 3行目の和
            // 使っていない条件をチェック
            if(m[ 2]+m[ 6]+m[10]+m[14]!=34) continue;       // 3列目の和
            if(m[ 0]+m[ 5]+m[10]+m[15]!=34) continue;       // 斜め(\)の和
            
            // 1〜Nまでちゃんと揃っているか調べる
            if(!checkAllNum(m)) continue;
            // チェックを潜り抜けたものだけを表示
            c++;
            disp(c,m);
        }while(next_perm(p,11,2));

        tm=System.nanoTime()-tm;        // Timer Stop
        System.out.printf("Runtime : %.3f [sec]\n",(double)tm/1e9);
    }
}

●実行結果

[1]
  4  9  5 16
 15  6 10  3
 14  7 11  2
  1 12  8 13

Runtime : 0.037 [sec]

※参考URL
東京都2007年<魔方陣>の画像 | 岡野朋一ブログ 〜数的処理 特講〜

魔方陣パズル - rscの日記
魔方陣パズル(2) - C言語 - rscの日記
4次の魔方陣プログラム - C言語 - rscの日記
数的推理の魔方陣の問題をPythonで解いてみた。 - rscの日記

第4版 スーパートレーニングプラス 数的推理

第4版 スーパートレーニングプラス 数的推理

畑中敦子の数的推理の大革命!(公務員試験/畑中敦子シリーズ)

畑中敦子の数的推理の大革命!(公務員試験/畑中敦子シリーズ)

数的推理がみるみるわかる! 解法の玉手箱[改訂版]

数的推理がみるみるわかる! 解法の玉手箱[改訂版]