人形の持ち主の論理パズルをJavaで解いてみた

 人形の持ち主の論理パズルJavaで解いてみました。

 P、Q、Rの3人が人形を2つずつ持っている。それらの6つの人形は(A〜Fとする)は目の色がそれぞれ異なり(黒、茶、青、緑、橙、灰)、髪の色もそれぞれ異なっている(茶、橙、金、銀、黒、赤)。
 1.ある者はAと黒い目の人形の2つを持っていて、別の者はBと茶髪の人形の2つを持っている。また、さらに別の者は橙色の髪の人形(Eではない)と茶色の目の人形の2つを持っている。
 2.Cの髪は金髪で、Qがこの人形を持っている。
 3.青い目の人形の髪は銀色で、この人形を持っているのはR。
 4.ある者はDと緑の目の人形の2つを持っている。
 5.ある者は橙色の目の人形と黒髪の人形の2つを持っている。
 さて、6つの人形それぞれの目の色、髪の色、持ち主は?

 ただし、色の名前が煩わいしいので次のように漢字一文字に書き直しました。

目の色:(黒、茶、青、緑、ヘイゼル、グレイ)→(黒、茶、青、緑、橙、灰)
髪の色:(ブラウン、ライトブラウン、ブロンド、アッシュブロンド、黒、赤)→(茶、橙、金、銀、黒、赤)

●DollPuzzle.java

/*
 * DollPuzzle.java
 */

import java.util.Arrays;

class DollPuzzle {
    static final String DOLL="ABCDEF";        // 固定
    static final String OWN ="PPQQRR";        // 要素を昇順にソートしたもの
    static final String EYE =sSort("黒茶青緑橙灰"); // 以下同様
    static final String HAIR=sSort("茶橙金銀黒赤");
    
    static char[] Own =OWN .toCharArray();          // 持ち主

    static String sSort(String s) {
        char[] c=s.toCharArray();
        
        Arrays.sort(c);
        return(new String(c)); 
    }

    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 getPos(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を返す. 
    }
    
    // b[]のyに対応するa[]のxを求めるメソッド
    static char getXof(char[] a, char[] b, char y){
        int n=getPos(b,y);
        if(n<0) return('\0');   // ないときは、'\0'を返す.
        else return(a[n]);      // あるときは、b[]のyに対するa[]のxを返す.
    }
    
    // オーナー条件
    static boolean check_ownnr(char[] a, char x, char[] b, char y){
        return(getXof(Own,a,x)==getXof(Own,b,y));
    }
    // 条件チェック: xからm個右側にyがあるか調べるメソッド
    static boolean check_cond(int m, char[] a, char x, char[] b, char y) {
        int n=getPos(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));
    }

    public static void main(String[] args) {
        char[] doll=DOLL.toCharArray();     // 人形(固定)
        // char[] own =OWN .toCharArray();  // 持ち主
        char[] eye =EYE .toCharArray();     // 目の色
        char[] hair=HAIR.toCharArray();     // 髪の色

        long tm=System.nanoTime();      // Timer Start
        
        Own =OWN .toCharArray();
        do{    //--- Own loop ---//
            
            if(!check_match(doll,'C',Own ,'Q')) continue; // 条件2
                        
            hair=HAIR.toCharArray();
            do{    //--- hair loop ---//
                if(!check_ownnr(doll,'B',hair,'茶')) continue; // 条件1
                if( check_match(doll,'B',hair,'茶')) continue; // 条件1
                if( check_ownnr(doll,'A',hair,'橙')) continue; // 条件1
                if( check_ownnr(doll,'A',hair,'茶')) continue; // 条件1
                if( check_ownnr(doll,'B',hair,'橙')) continue; // 条件1
                if( check_match(doll,'E',hair,'橙')) continue; // 条件1
                if(!check_match(doll,'C',hair,'金')) continue; // 条件2
                
                eye =EYE .toCharArray();
                do{    //--- eye loop ---//
                    if(!check_ownnr(doll,'A',eye ,'黒')) continue; // 条件1
                    if( check_match(doll,'A',eye ,'黒')) continue; // 条件1
                    if(!check_ownnr(hair,'橙',eye ,'茶')) continue; // 条件1
                    if( check_match(hair,'橙',eye ,'茶')) continue; // 条件1
                    if( check_ownnr(doll,'B',eye ,'黒')) continue; // 条件1
                    if(!check_match(eye ,'青',hair,'銀')) continue; // 条件3
                    if(!check_match(Own ,'R',eye ,'青')) continue; // 条件3
                    if(!check_ownnr(doll,'D',eye ,'緑')) continue; // 条件4
                    if( check_match(doll,'D',eye ,'緑')) continue; // 条件4
                    if(!check_ownnr(eye ,'橙',hair,'黒')) continue; // 条件5
                    if( check_match(eye ,'橙',hair,'黒')) continue; // 条件5

                    // チェックを潜り抜けたものだけを表示
                    System.out.println("D: "+new String(doll));
                    System.out.println("O: "+new String(Own ));
                    System.out.println("E: "+new String(eye ));
                    System.out.println("H: "+new String(hair));
                    System.out.println();
                 }while(next_perm(eye ,6,6));
            }while(next_perm(hair,6,6));
        }while(next_perm(Own ,6,6));

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


●実行結果

D: ABCDEF
O: RPQPRQ
E: 青緑茶橙黒灰
H: 銀黒金茶赤橙

Runtime : 0.019 [sec]

論理パズル101―推理の楽しさ、ひらめきの快感 (ブルーバックス)

論理パズル101―推理の楽しさ、ひらめきの快感 (ブルーバックス)