解决爱因斯坦出的头脑风暴测试题

        经常遇见这样的问题,却往往没人回答,于是发贴者洋洋自得?猜的,哈哈。
或许在那个年代,要做出这样的问题非常难,我感到奇怪的是爱因斯坦为什么出这样的题目,考察人的什么思维?又是怎么出的?难道考察天才的某一特性:解决问题时拥有超强的暂时记忆,能容忍很大的不确定性?
现在还拿出来吼吼,当我们程序员不存在,郁闷之余,逐写代码解决。

 解题思路:
1.1~15个已知条件写成c1~15个条件方法;
2.预先求1..5的所有排列;
3.对每个属性进行排列;
4.对6个属性的排列进行组合;
5.上面的排列组合有24.8832亿种,每种组合在合适的位置过滤1~15个条件(合适位置的选择:条件关联的属性已被赋值,且最浅循环。);
6.执行结果有7种排列组合,其中可能养鱼的分别有:德国、挪威、丹麦

package  com.game;

import  java.util.ArrayList;
import  java.util.Arrays;
import  java.util.List;

/**
 * 
<pre>
    爱因斯坦出的测试题,据说世界98%的人答不出!来看看这道爱因斯坦出的测试题, 他说世界上有98%的人回答不出, 
    看看你是否属于另外的2%:
    1. 有5栋5种颜色的房子 
    2. 每一位房子的主人国籍都不同 
    3. 这5个人每人只喝一个牌子的饮料, 只抽一个牌子的香烟, 只养一 
    种宠物 
    4. 没有人有相同的宠物, 抽相同牌子的香烟, 喝相同的饮料 
    已知条件: 
    1. 英国人住在红房子里 
    2. 瑞典人养了一条狗 
    3. 丹麦人喝茶 
    4. 绿房子在白房子左边 
    5. 绿房子主人喝咖啡 
    6. 抽PALL MALL烟的人养了一只鸟 
    7. 黄房子主人抽DUNHILL烟 
    8. 住在中间那间房子的人喝牛奶 
    9. 挪威人住在第一间房子 
    10. 抽混合烟的人住在养猫人的旁边 
    11. 养马人住在DUNHILL烟的人旁边 
    12. 抽BLUE MASTER烟的人喝啤酒 
    13. 德国人抽PRINCE烟 
    14. 挪威人住在蓝房子旁边 
    15. 抽混合烟的人的邻居喝矿泉水
    问题是:谁养鱼?
</pre>
 * 
@author zfzheng
 * {
@value 不好意思,偶便是2%中较笨的一个 :)}
 *
 
*/

public   class  EinsteinProblem  {
    
private final static int[] NO={1,2,3,4,5};
    
private final static String[] COLOR={"","","绿","",""};
    
private final static String[] NATIONALITY={"英国","瑞典","丹麦","挪威","德国"};
    
private final static String[] DRINK={"","咖啡","牛奶","啤酒","矿泉水"};
    
private final static String[] SMOKE={"PALL MALL","DUNHILL","BLUE MASTER","PRINCE","混合烟"};
    
private final static String[] PET={"","","","",""};
    
//排列列表,{[1,2,3,4,5],[1,2,3,5,4],......}
    private List<int[]> pList=new ArrayList<int[]>();
    
    
static class Combine{
        
int no;//房间编号
        String color;//房子颜色
        String nationality;//国籍
        String drink;//饮料
        String smoke;//香烟
        String pet;//宠物        
        
        
public String toString(){
            
return no+" "+color+" "+nationality+" "+drink+" "+smoke+" "+pet;
        }

    }

    
    
// 1. 英国人住在红房子里 
    private boolean c1(Combine[] items){
        Combine item;
        
for(int i=0,n=items.length;i<n;i++){
            item
=items[i];
            
if(item.nationality.equals("英国")){
                
return item.color.equals("");
            }

        }

        
return false;
    }

    
    
//2. 瑞典人养了一条狗 
    private boolean c2(Combine[] items){
        Combine item;
        
for(int i=0,n=items.length;i<n;i++){
            item
=items[i];
            
if(item.nationality.equals("瑞典")){
                
return item.pet.equals("");
            }

        }

        
return false;
    }
    
    
    
//3. 丹麦人喝茶 
    private boolean c3(Combine[] items){
        Combine item;
        
for(int i=0,n=items.length;i<n;i++){
            item
=items[i];
            
if(item.nationality.equals("丹麦")){
                
return item.drink.equals("");
            }

        }

        
return false;
    }
    
    
    
//4. 绿房子在白房子左边 
    private boolean c4(Combine[] items){
        Combine item;
        
for(int i=0,n=items.length;i<n;i++){
            item
=items[i];
            
if(item.color.equals("绿")){
                
for(int j=i+1;j<n;j++){
                    
if(items[j].color.equals("")){
                        
return true;
                    }

                }

                
return false;
            }

        }

        
return false;
    }
    
    
    
// 5. 绿房子主人喝咖啡  
    private boolean c5(Combine[] items){
        Combine item;
        
for(int i=0,n=items.length;i<n;i++){
            item
=items[i];
            
if(item.color.equals("绿")){
                
return item.drink.equals("咖啡");
            }

        }

        
return false;
    }
    

    
//6. 抽PALL MALL烟的人养了一只鸟 
    private boolean c6(Combine[] items){
        Combine item;
        
for(int i=0,n=items.length;i<n;i++){
            item
=items[i];
            
if(item.smoke.equals("PALL MALL")){
                
return item.pet.equals("");
            }

        }

        
return false;
    }
    
    
    
//7. 黄房子主人抽DUNHILL烟 
    private boolean c7(Combine[] items){
        Combine item;
        
for(int i=0,n=items.length;i<n;i++){
            item
=items[i];
            
if(item.smoke.equals("DUNHILL")){
                
return item.color.equals("");
            }

        }

        
return false;
    }

    
    
//8. 住在中间那间房子的人喝牛奶 
    private boolean c8(Combine[] items){
        Combine item;
        
for(int i=0,n=items.length;i<n;i++){
            item
=items[i];
            
if(item.no==3){
                
return item.drink.equals("牛奶");
            }

        }

        
return false;
    }

    
    
//9. 挪威人住在第一间房子
    private boolean c9(Combine[] items){
        Combine item;
        
for(int i=0,n=items.length;i<n;i++){
            item
=items[i];
            
if(item.no==1){
                
return item.nationality.equals("挪威");
            }

        }

        
return false;
    }

    
//10. 抽混合烟的人住在养猫人的旁边 
    private boolean c10(Combine[] items){
        Combine item;
        
for(int i=0,n=items.length;i<n;i++){
            item
=items[i];
            
if(item.smoke.equals("混合烟")){
                
return (i>0&&items[i-1].pet.equals(""))||(i<n-1&&items[i+1].pet.equals(""));
            }

        }

        
return false;
    }
    
    
    
//11. 养马人住在DUNHILL烟的人旁边 
    private boolean c11(Combine[] items){
        Combine item;
        
for(int i=0,n=items.length;i<n;i++){
            item
=items[i];
            
if(item.smoke.equals("DUNHILL")){
                
return (i>0&&items[i-1].pet.equals(""))||(i<n-1&&items[i+1].pet.equals(""));
            }

        }

        
return false;
    }

    
    
//12. 抽BLUE MASTER烟的人喝啤酒 
    private boolean c12(Combine[] items){
        Combine item;
        
for(int i=0,n=items.length;i<n;i++){
            item
=items[i];
            
if(item.smoke.equals("BLUE MASTER")){
                
return item.drink.equals("啤酒");
            }

        }

        
return false;
    }
    
    
    
//13. 德国人抽PRINCE烟 
    private boolean c13(Combine[] items){
        Combine item;
        
for(int i=0,n=items.length;i<n;i++){
            item
=items[i];
            
if(item.smoke.equals("PRINCE")){
                
return item.nationality.equals("德国");
            }

        }

        
return false;
    }
    
    
    
// 14. 挪威人住在蓝房子旁边 
    private boolean c14(Combine[] items){
        Combine item;
        
for(int i=0,n=items.length;i<n;i++){
            item
=items[i];
            
if(item.nationality.equals("挪威")){
                
return (i>0&&items[i-1].color.equals(""))||(i<n-1&&items[i+1].color.equals(""));
            }

        }

        
return false;
    }
    
    
    
// 15. 抽混合烟的人的邻居喝矿泉水  
    private boolean c15(Combine[] items){
        Combine item;
        
for(int i=0,n=items.length;i<n;i++){
            item
=items[i];
            
if(item.smoke.equals("混合烟")){
                
return (i>0&&items[i-1].drink.equals("矿泉水"))||(i<n-1&&items[i+1].drink.equals("矿泉水"));
            }

        }

        
return false;
    }
    
    
    
private void assignCombine(Combine[] items){
        
int matchedCount=0;
        
int n=pList.size();
        
for(int i_color=0;i_color<n;i_color++){
            assignColor(items,pList.get(i_color));
            
if(!c4(items))continue;// 4. 绿房子在白房子左边 
            for(int i_nationality=0;i_nationality<n;i_nationality++){
                assignNationality(items,pList.get(i_nationality));
                
if(!c1(items))continue;//1. 英国人住在红房子里 
                if(!c9(items))continue;//9. 挪威人住在第一间房子
                if(!c14(items))continue;//14. 挪威人住在蓝房子旁边
                for(int i_drink=0;i_drink<n;i_drink++){
                    assignDrink(items,pList.get(i_drink));
                    
if(!c3(items))continue;//3. 丹麦人喝茶 
                    if(!c5(items))continue;// 5. 绿房子主人喝咖啡 
                    if(!c8(items))continue;//8. 住在中间那间房子的人喝牛奶 
                    for(int i_smoke=0;i_smoke<n;i_smoke++){
                        assignSmoke(items,pList.get(i_smoke));
                        
if(!c7(items))continue;// 7. 黄房子主人抽DUNHILL烟
                        if(!c12(items))continue;//12. 抽BLUE MASTER烟的人喝啤酒 
                        if(!c13(items))continue;//13. 德国人抽PRINCE烟
                        if(!c15(items))continue;//15. 抽混合烟的人的邻居喝矿泉水
                        for(int i_pet=0;i_pet<n;i_pet++){
                            assignPet(items,pList.get(i_pet));
                            
if(!c2(items))continue;//2. 瑞典人养了一条狗 
                            if(!c6(items))continue;//6. 抽PALL MALL烟的人养了一只鸟
                            if(!c10(items))continue;//10. 抽混合烟的人住在养猫人的旁边 
                            if(!c11(items))continue;// 11. 养马人住在DUNHILL烟的人旁边
                            matchedCount++;
                            dumpCombine(items);
                        }

                    }

                }
                
            }

        }
        
        System.out.println(
"Matched count="+matchedCount);
    }
    
    
    
private void assignColor(Combine[] items,int[] order){
        
for(int i=0,n=items.length;i<n;i++){
            items[i].color
=COLOR[order[i]-1];
        }

    }

    
private void assignNationality(Combine[] items,int[] order){
        
for(int i=0,n=items.length;i<n;i++){
            items[i].nationality
=NATIONALITY[order[i]-1];
        }

    }

    
    
    
private void assignDrink(Combine[] items,int[] order){
        
for(int i=0,n=items.length;i<n;i++){
            items[i].drink
=DRINK[order[i]-1];
        }

    }

    
private void assignSmoke(Combine[] items,int[] order){
        
for(int i=0,n=items.length;i<n;i++){
            items[i].smoke
=SMOKE[order[i]-1];
        }

    }

    
private void assignPet(Combine[] items,int[] order){
        
for(int i=0,n=items.length;i<n;i++){
            items[i].pet
=PET[order[i]-1];
        }

    }
    
    
    
    
private void dumpCombine(Combine[] items){
        StringBuffer s
=new StringBuffer();
        
for(int i=0;i<items.length;i++){
            s.append(items[i]).append(
" ");
        }

        System.out.println(s
+" ");
    }

    
    
//排列
    private void readyPermutation(int n){
        pList.clear();
        
boolean[] selected=new boolean[n];
        Arrays.fill(selected, 
false);
        
int[] v=new int[n];
        Arrays.fill(v, 
-1);
        doPermutation(selected,v,n,
0);
    }

    
    
/**
     * 递归、回溯求排列
     
*/

    
private void doPermutation(boolean[] selected, int[] v, int n, int filledCount){
        
for(int i=filledCount;i<n;i++){
            
for(int j=0;j<n;j++){
                
if(!selected[j]){
                    selected[j]
=true;
                    v[i]
=j+1;
                    
if(i==n-1){
                        gatherPermutationResult(v);
                    }

                    doPermutation(selected,v,n,i
+1);    
                    
//回溯
                    selected[j]=false;
                    v[i]
=-1;
                }

            }
            
                        
        }

    }

    
    
private void gatherPermutationResult(int[] v){
        
for(int i=0;i<v.length;i++){
            
if(v[i]==-1){
                
return;
            }

        }

        pList.add(v.clone());
    }

    
    
private void doMatch(){
        
//初始化
        Combine[] items=new Combine[5];
        
for(int i=0;i<items.length;i++){
            items[i]
=new Combine();
            items[i].no
=NO[i];
        }

        
//准备排列组合
        readyPermutation(5);
        
//匹配
        assignCombine(items);    
    }

    
    
    
public static void main(String[] args) {
        
new EinsteinProblem().doMatch();
    }
    
}

 

执行输出

1 绿 挪威 咖啡 PALL MALL 鸟
2 蓝 德国 矿泉水 PRINCE 猫
3 红 英国 牛奶 混合烟 马
4 黄 丹麦 茶 DUNHILL 鱼
5 白 瑞典 啤酒 BLUE MASTER 狗


1 绿 挪威 咖啡 PALL MALL 鸟
2 蓝 德国 矿泉水 PRINCE 鱼
3 红 英国 牛奶 混合烟 马
4 黄 丹麦 茶 DUNHILL 猫
5 白 瑞典 啤酒 BLUE MASTER 狗


1 绿 挪威 咖啡 PALL MALL 鸟
2 蓝 德国 矿泉水 PRINCE 猫
3 白 瑞典 牛奶 混合烟 狗
4 红 英国 啤酒 BLUE MASTER 马
5 黄 丹麦 茶 DUNHILL 鱼


1 绿 挪威 咖啡 PALL MALL 鸟
2 蓝 德国 矿泉水 PRINCE 猫
3 白 瑞典 牛奶 混合烟 狗
4 黄 丹麦 茶 DUNHILL 鱼
5 红 英国 啤酒 BLUE MASTER 马


1 绿 挪威 咖啡 PALL MALL 鸟
2 蓝 德国 矿泉水 PRINCE 鱼
3 白 瑞典 牛奶 混合烟 狗
4 黄 丹麦 茶 DUNHILL 猫
5 红 英国 啤酒 BLUE MASTER 马


1 绿 挪威 咖啡 混合烟 鱼
2 蓝 德国 矿泉水 PRINCE 猫
3 黄 瑞典 牛奶 DUNHILL 狗
4 红 英国 啤酒 BLUE MASTER 马
5 白 丹麦 茶 PALL MALL 鸟


1 黄 挪威 矿泉水 DUNHILL 猫
2 蓝 丹麦 茶 混合烟 马
3 红 英国 牛奶 PALL MALL 鸟
4 绿 德国 咖啡 PRINCE 鱼
5 白 瑞典 啤酒 BLUE MASTER 狗


Matched count=7

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值