Einstein's riddle in Java

 ついでに、今度は、Javaに翻訳してみました。(^_^;

●EinsteinsRiddle.java

/*
 * EinsteinsRiddle.java
 * # : 12345
 * N : NDEGS
 * H : YBRGW
 * P : CHBFD
 * D : WTMCB
 * T : DMPRB
 */

class EinsteinsRiddle {
    static void swap(char[] s, int i, int j) {
        char t = s[i]; s[i] = s[j]; s[j] = t;
    }
    // 順列生成
    static boolean next_perm(char[] 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);
    }
    
    // xがa[]の何番目にあるか調べる関数(メソッド)
    static int get_pos(char[] a, char x) {
        for(int i=0; i<a.length; i++)
            if(a[i]==x) return(i);  // あるときは、0〜a.length-1を返す. 
        return(-1);                 // ないときは、-1を返す.
    }

    // 条件チェック:a[]のxからm個右側にb[]のyがあるか調べる関数(メソッド)
    static boolean check_cond(int m, char[] a, char x, char[] b, char y) {
        int n=get_pos(a,x);
    	
        if(n<0||a.length<=m+n) return(false);
        if(b[m+n]==y)          return(true ); else return(false);
    }

    // マッチング条件
    static boolean check_match(char[] a, char x, char[] b, char y) {
        return(check_cond(0,a,x,b,y));
    }

    // 順序付き隣接条件(左からx,yの順で隣接)
    static boolean check_adj_1(char[] a, char x, char[] b, char y) {
        return(check_cond(1,a,x,b,y));
    }

    // 隣接条件(順不定)
    static boolean check_adj_2(char[] a, char x, char[] b, char y) {
        return(check_adj_1(a,x,b,y)||check_adj_1(b,y,a,x));
    }
    
    static final String PLACE ="12345";    // 固定
    static final String NATION="DEGNS";    // 要素を昇順にソートしたもの
    static final String HOUSE ="BGRWY";    // 以下同様
    static final String PET   ="BCDFH";
    static final String DRINK ="BCMTW";
    static final String TABACO="BDMPR";

    static final String[] Nation={
        "D:デンマーク",
        "E:イギリス",
        "G:ドイツ",
        "N:ノルウェー",
        "S:スウェーデン"
    };
    
    public static void main(String[] args) {
        char[] place =PLACE .toCharArray();    // 場所(固定)
        char[] nation=NATION.toCharArray();    // 国、国籍
        char[] house =HOUSE .toCharArray();    // 家
        char[] pet   =PET   .toCharArray();    // ペット
        char[] drink =DRINK .toCharArray();    // 飲み物
        char[] tabaco=TABACO.toCharArray();    // タバコ(ポルトガル語)

        long tm=System.currentTimeMillis();            // Timer Start
        
        nation=NATION.toCharArray();
        do{    // nation loop
            if(!check_match(nation,'N',place, '1')) continue;    // 条件09
            house=HOUSE.toCharArray();
            do{    // house loop
                if(!check_match(nation,'E',house, 'R')) continue;    // 条件01
                if(!check_adj_1(house, 'G',house, 'W')) continue;    // 条件04
                if(!check_adj_2(nation,'N',house, 'B')) continue;    // 条件14
                pet=PET.toCharArray();
                do{    // pet loop
                    if(!check_match(nation,'S',pet,   'D')) continue;    // 条件02
                    drink=DRINK.toCharArray();
                    do{    // drink loop
                        if(!check_match(nation,'D',drink, 'T')) continue;    // 条件03
                        if(!check_match(house, 'G',drink, 'C')) continue;    // 条件05
                        if(!check_match(place, '3',drink, 'M')) continue;    // 条件08
                        tabaco=TABACO.toCharArray();
                        do{    // tabaco loop
                            if(!check_match(tabaco,'P',pet,   'B')) continue;    // 条件06
                            if(!check_match(house, 'Y',tabaco,'D')) continue;    // 条件07
                            if(!check_adj_2(tabaco,'M',pet,   'C')) continue;    // 条件10
                            if(!check_adj_2(pet,   'H',tabaco,'D')) continue;    // 条件11
                            if(!check_match(tabaco,'B',drink, 'B')) continue;    // 条件12
                            if(!check_match(nation,'G',tabaco,'R')) continue;    // 条件13
                            if(!check_adj_2(tabaco,'M',drink, 'W')) continue;    // 条件15
                        
                            // チェックを潜り抜けたものだけを表示
                            System.out.println("#: "+new String(place ));
                            System.out.println("N: "+new String(nation));
                            System.out.println("H: "+new String(house ));
                            System.out.println("P: "+new String(pet   ));
                            System.out.println("D: "+new String(drink ));
                            System.out.println("T: "+new String(tabaco));
                            System.out.println();
                        
                            System.out.println("∴"
                                +Nation[NATION.indexOf(nation[get_pos(pet,'F')])]+"人");
                        }while(next_perm(tabaco,5,5));
                    }while(next_perm(drink,5,5));
                }while(next_perm(pet,5,5));
            }while(next_perm(house,5,5));
        }while(next_perm(nation,5,5));

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

●実行結果

#: 12345
N: NDEGS
H: YBRGW
P: CHBFD
D: WTMCB
T: DMPRB

∴G:ドイツ人
Runtime : 0.018 [sec]

※参考URL
【プログラム クイズ】 アインシュタインのなぞなぞ (Einstein's Riddle)
よしいずの雑記帳  再帰呼び出しを使わずに順列や組合せを得るC言語プログラム (2)

●明解Java 入門編 [単行本]  柴田 望洋 (著)

明解Java 入門編

明解Java 入門編

●やさしいJava 第4版 [単行本]  高橋 麻奈 (著)
やさしいJava 第4版

やさしいJava 第4版

●わかりやすいJava入門編 [単行本]  川場 隆 (著)
わかりやすいJava入門編

わかりやすいJava入門編

●わかりやすいJava オブジェクト指向編 [単行本]  川場 隆 (著)
わかりやすいJavaオブジェクト指向編

わかりやすいJavaオブジェクト指向編

●改訂第2版 Java言語プログラミングレッスン (上) [大型本]  結城 浩 (著)
改訂第2版 Java言語プログラミングレッスン (上)

改訂第2版 Java言語プログラミングレッスン (上)

●改訂第2版 Java言語プログラミングレッスン (下) [大型本]  結城 浩 (著)
改訂第2版 Java言語プログラミングレッスン (下)

改訂第2版 Java言語プログラミングレッスン (下)