1. 程式人生 > >愛因斯坦謎題 誰養魚 C 版

愛因斯坦謎題 誰養魚 C 版

               

    一個偶然的機會再次接觸到了愛因斯坦謎題,一時來了興致,用C#做了一個程式,看看到底是誰養魚(大學畢業後接觸過這道題,不過很遺憾,那時的我沒有成為2%的人,所以不知道是誰在養魚)?

這道迷題出自1981年柏林的德國邏輯思考學院,據說世界上只有2%的人能出答案,就連大名鼎鼎的愛因斯坦也成為此題大傷腦。愛因斯坦謎題的中文表述是這樣的:

155種顏色的房子

2每一位房子的主人國籍都不同

3這五個人每人只喝一個牌子的飲料,只抽一個牌子的香菸,只養一種寵物

4沒有人有相同的寵物,抽相同牌子的煙,喝相同牌子的飲料

已知條件:

1英國人住在紅房子裡

2瑞典人養了一條狗

3丹麥人喝?

4綠房子在白房子的左邊

5綠房子主人喝咖啡

6pallmall煙的人養了一隻鳥

7黃房子主人抽dunhill

8住在中間房子的人喝牛奶

9挪威人住在第一間房子

10.抽混合煙的人住在養貓人的旁邊

11.養馬人住在抽dunhill煙人的旁邊

12.抽bluemaster煙的人喝啤酒

13.德國人抽prince

14.挪威人住在藍房子旁邊

15.抽混合煙的人的鄰居喝礦泉水

問題:誰養魚?

很遺憾的是,這個中文表述有問題,至少有以下幾方面的歧義:

一、如何區分左右?二、已知條件中的第4條,綠房子在白房子的左邊,是緊鄰?還是可以分開?三、第一個房子,從什麼方向開始算起,左,還是右?

如果僅把上面的第二點提到的綠房子在白房子的左邊,不限於緊鄰,則會出現

7組符合條件的組合,3個答案:丹麥人養魚(3組)、德國人養魚(3組)、挪威人養魚(1組)。

這顯然不符合愛因斯坦謎題的本意,所以又查了查英文原題,結果真相大白,其嚴謹的表述有效的消除了以上的歧義。那最終的結果究竟又如何呢?

英文原題:

The Einstein Puzzle

There are 5 houses in five different colors. They are lined up in a row side by side.

In each house lives a person with a different nationality.

These 5 owners drink a certain drink, smoke a certain brand of tobacco and keep a certain pet.

No owners have the same pet, smoke the same tobacco, or drink the same drink.

As you look at the 5 houses from across the street, the green house is adjacentwoog註釋:adjacent adj,毗連的,鄰近的,接近的;n,近鄰) to the left of the white house

The Big Question is:

Who owns the Fish?

CLUES:

1The Brit lives in the red house

2The Swede keeps dogs as pets

3The Dane drinks tea

4The green house is on the immediate left of the white house as you stare at the front of the 5 houses

5The green house owner drinks coffee

6The person who smokes Pall Mall raises birds

7The owner of the yellow house smokes Dunhill

8The man living in the house right in the center drinks milk

9The Norwegian lives in the first house

10The man who smokes Blends lives next to the one who keeps cats

11The man who keeps horses lives next to the one who smokes Dunhill

12The owner who smokes Bluemaster drinks juice

13The German smokes Prince

14The Norwegian lives next to the blue house

15The man who smokes Blend has a neighbor who drinks water.

相關程式碼如下(考慮了兩種情況,當#define FastCompute時,僅有一組答案):

[c-sharp] view plain copy print?
  1. //[葉帆工作室] http://blog.csdn.net/yefanqiu 
  2. #define FastCompute     
  3. using System;  
  4. using System.Collections.Generic;  
  5. using System.ComponentModel;  
  6. using System.Data;  
  7. using System.Drawing;  
  8. using System.Text;  
  9. using System.Windows.Forms;  
  10. using System.Diagnostics;      
  11. namespace Einstein  
  12. {  
  13.     public partial class frmMain : Form  
  14.     {  
  15.         public frmMain()  
  16.         {  
  17.             InitializeComponent();  
  18.         }  
  19.         privatevoid btnRun_Click(object sender, EventArgs e)  
  20.         {                                                    
  21.             Arithmetic arithmetic = new Arithmetic();        
  22.             DateTime dt = DateTime.Now;  
  23.             string  result = arithmetic.DoResult();  
  24.             MessageBox.Show(result + "/r/n耗時:" + (DateTime.Now - dt).TotalSeconds.ToString() + "秒");  
  25.         }             
  26.     }  
  27.     publicclass Arithmetic  
  28.     {  
  29.         string[] people   = newstring[] { "英國""瑞典""丹麥""挪威""德國" };  
  30.         string[] house = newstring[] { "紅""綠""白""黃""藍" };  
  31.         string[] drink = newstring[] { "茶""咖啡""牛奶""啤酒""水" };  
  32.         string[] smoke = newstring[] { "Pall Mall""Dunhill""Blends""Blue Master""Prince" };  
  33.         string[] pet = newstring[] { "狗""鳥""貓""馬""魚" };  
  34.         List<string[]> lstCombination = new List<string[]>();   //存放全部結果(預刪減後的結果)
  35.         List<string[]> lstCombination0 = new List<string[]>();  
  36.         List<string[]> lstCombination1 = new List<string[]>();  
  37.         List<string[]> lstCombination2 = new List<string[]>();  
  38.         List<string[]> lstCombination3 = new List<string[]>();  
  39.         List<string[]> lstCombination4 = new List<string[]>();  
  40.         publicstring DoResult()  
  41.         {  
  42.             string[,] result = newstring[5, 5];  
  43.             //生成全部的組合
  44.             MakeCombination();  
  45.             //預剔除不符合條件的組合
  46.             EliminateCombination();  
  47.             //獲得有可能的組合0
  48.             EliminateCombination0();  
  49.             //獲得有可能的組合1
  50.             EliminateCombination1();  
  51.             //獲得有可能的組合2
  52.             EliminateCombination2();  
  53.             //獲得有可能的組合3
  54.             EliminateCombination3();  
  55.             //獲得有可能的組合4
  56.             EliminateCombination4();  
  57.             string strInfo = "";  
  58.             int intNum = 0;  
  59.             for (int i = 0; i < lstCombination0.Count; i++)      
  60.             {  
  61.                 ToCombination(result, 0, lstCombination0,i);  
  62.                 for (int j =0; j < lstCombination1.Count; j++)    
  63.                 {  
  64.                     ToCombination(result, 1, lstCombination1,j);  
  65.                     for (int k = 0; k < lstCombination2.Count; k++)   
  66.                     {  
  67.                         ToCombination(result,  2,lstCombination2, k);  
  68.                         for (int l =0; l < lstCombination3.Count; l++)    
  69.                         {  
  70.                             ToCombination(result,  3,lstCombination3, l);  
  71.                             for (int m =0; m < lstCombination4.Count; m++)   
  72.                             {  
  73.                                 ToCombination(result, 4,lstCombination4, m);  
  74.                                 bool Flag=true;  
  75.                                 for (int e = 0; e < 5; e++)  
  76.                                 {  
  77.                                     if (result[0, e] == result[1, e] || result[0, e] == result[2, e] || result[0, e] == result[3, e] || result[0, e] == result[4, e] ||  
  78.                                         result[1, e] == result[2, e] || result[1, e] == result[3, e] || result[1, e] == result[4, e] ||  
  79.                                         result[2, e] == result[3, e] || result[2, e] == result[4, e] ||  
  80.                                         result[3, e] == result[4, e])  
  81.                                     {  
  82.                                         Flag = false;  
  83.                                         break;  
  84.                                     }  
  85.                                 }  
  86.                                 //判斷組合是否成立
  87.                                 if (Flag && Judge(result))  
  88.                                 {  
  89.                                     strInfo += "---------------- " + (++intNum).ToString()+" ----------------/r/n";  
  90.                                     for (int ii = 0; ii < 5; ii++)  
  91.                                     {  
  92.                                         for (int jj = 0; jj < 5; jj++)  
  93.                                         {  
  94.                                             strInfo += result[ii, jj] + " ";  
  95.                                         }  
  96.                                         strInfo += "/r/n";  
  97.                                     }  
  98. #if FastCompute
  99.                                     strInfo += "------------------------------------/r/n";  
  100.                                     return strInfo;  
  101. #endif
  102.                                 }  
  103.                             }  
  104.                         }  
  105.                     }  
  106.                 }  
  107.             }  
  108.             strInfo += "------------------------------------/r/n";  
  109.             return strInfo;             
  110.         }  
  111.         privatevoid ToCombination(string[,] result,int index, List<string[]>  lst,int num)  
  112.         {  
  113.             for (int i = 0; i < 5; i++)  
  114.             {  
  115.                 result[index, i] = lst[num][i];  
  116.             }  
  117.         }  
  118.         //生成全部的組合
  119.         privatevoid MakeCombination()  
  120.         {  
  121.             string[] combination = newstring[5];  
  122.             //5*5*5*5*5=3125
  123.             for (int i = 0; i < 5; i++) //國籍
  124.             {  
  125.                 combination[0] = people[i];  
  126.                 for (int j = 0; j < 5; j++)  //房子
  127.                 {  
  128.                     combination[1] = house[j];  
  129.                     for (int k = 0; k < 5; k++)  //飲料
  130.                     {  
  131.                         combination[2] = drink[k];  
  132.                         for (int l = 0; l < 5; l++)  //香菸
  133.                         {  
  134.                             combination[3] = smoke[l];  
  135.                             for (int m = 0; m < 5; m++)  //寵物
  136.                             {  
  137.                                 combination[4] = pet[m];  
  138.                                 lstCombination.Add((string[])combination.Clone());  
  139.                             }  
  140.                         }  
  141.                     }  
  142.                 }  
  143.             }  
  144.         }  
  145.         //剔除組合的判斷條件
  146.         privatebool JudgeCombination(string[] combination)  
  147.         {  
  148.             //1、英國住紅房子
  149.             if (combination[0] == "英國" && combination[1] != "紅"returnfalse;  
  150.             //2、瑞典養狗
  151.             if (combination[0] == "瑞典" && combination[4] != "狗"returnfalse;  
  152.             //3、丹麥喝茶
  153.             if (combination[0] == "丹麥" && combination[2] != "茶"returnfalse;  
  154.             //5、綠房子主喝咖啡
  155.             if (combination[1] == "綠" && combination[2] != "咖啡"returnfalse;  
  156.             //6、抽Pall Mall香菸的養鳥
  157.             if (combination[3] == "Pall Mall" && combination[4] != "鳥"returnfalse;  
  158.             //7、黃房子主抽Dunhill香菸
  159.             if (combination[1] == "黃" && combination[3] != "Dunhill"returnfalse;  
  160.             //12、抽Blue Master的喝啤酒
  161.             if (combination[3] == "Blue Master" && combination[2] != "啤酒"returnfalse;  
  162.             //13、德國抽Prince香菸
  163.             if (combination[0] == "德國" && combination[3] != "Prince"returnfalse;  
  164.             returntrue;  
  165.         }  
  166.         //預剔除不符合條件的組合
  167.         privatevoid EliminateCombination()  
  168.         {  
  169.             string[] combination=newstring[5];  
  170.             int num=lstCombination.Count;  
  171.             int index = 0;  
  172.             while ((num--)>0)  
  173.             {  
  174.                 if (!JudgeCombination(lstCombination[index]))  
  175.                 {  
  176.                     lstCombination.RemoveAt(index);  
  177.                 }  
  178.                 else
  179.                 {  
  180.                     index++;  
  181.                 }                  
  182.             }  
  183.         }  
  184.         //建立組合0
  185.         privatevoid EliminateCombination0()  
  186.         {  
  187.             lstCombination0.Clear();   
  188.             foreach (string[] combination in lstCombination)  
  189.             {  
  190.                 //combination[1] != "紅" && combination[1] != "藍" && combination[1] != "白" && combination[1] != "綠"
  191. #if FastCompute
  192.                 if (combination[0] == "挪威" && combination[1] == "黃" && combination[2] != "牛奶" && combination[2] != "茶" && combination[3] != "Prince" && combination[4] != "狗")  
  193. #else
  194.                 if (combination[0] == "挪威" && combination[1] != "紅" && combination[1] != "藍" && combination[1] != "白"  && combination[2] != "牛奶" && combination[2] != "茶" && combination[3] != "Prince" && combination[4] != "狗")  
  195. #endif
  196.                 {            
  197.                     lstCombination0.Add(combination);  
  198.                 }                                                                         
  199.             }      
  200.         }  
  201.         //建立組合1
  202.         privatevoid EliminateCombination1()  
  203.         {  
  204.             lstCombination1.Clear();  
  205.             foreach (string[] combination in lstCombination)  
  206.             {  
  207.                 if (combination[0] != "挪威" &&  combination[1] == "藍" && combination[2] != "牛奶")  
  208.                 {  
  209.                     lstCombination1.Add(combination);  
  210.                 }  
  211.             }  
  212.         }  
  213.         //建立組合2
  214.         privatevoid EliminateCombination2()  
  215.         {  
  216.             lstCombination2.Clear();  
  217.             foreach (string[] combination in lstCombination)  
  218.             {  
  219. #if FastCompute
  220.                 if (combination[0] != "挪威" && combination[0] != "丹麥" && combination[1] != "藍" && combination[1] != "黃" && combination[1] != "白" && combination[2] == "牛奶")  
  221. #else               
  222.                 if (combination[0] != "挪威" && combination[0] != "丹麥" && combination[1] != "藍"  && combination[2] == "牛奶")  
  223. #endif
  224.                 {  
  225.                     lstCombination2.Add(combination);  
  226.                 }  
  227.             }  
  228.         }  
  229.         //建立組合3
  230.         privatevoid EliminateCombination3()  
  231.         {  
  232.             lstCombination3.Clear();  
  233.             foreach (string[] combination in lstCombination)  
  234.             {  
  235. #if FastCompute
  236.                 if (combination[0] != "挪威" && combination[1] != "黃" && combination[1] != "藍" && combination[2] != "牛奶")  
  237. #else
  238.                 if (combination[0] != "挪威" && combination[1] != "藍" && combination[2] != "牛奶")  
  239. #endif
  240.                 {  
  241.                     lstCombination3.Add(combination);  
  242.                 }  
  243.             }  
  244.         }  
  245.         //建立組合4
  246.         privatevoid EliminateCombination4()  
  247.         {  
  248.             lstCombination4.Clear();  
  249.             foreach (string[] combination in lstCombination)  
  250.             {  
  251. #if FastCompute
  252.                 if (combination[0] != "挪威" && combination[1] != "黃" && combination[1] != "藍" && combination[1] != "綠" && combination[2] != "牛奶")  
  253. #else               
  254.                 if (combination[0] != "挪威" && combination[1] != "藍" && combination[1] != "綠" && combination[2] != "牛奶")  
  255. #endif
  256.                 {  
  257.                     lstCombination4.Add(combination);  
  258.                 }  
  259.             }  
  260.         }  
  261.         //判斷
  262.         privatestaticbool Judge(string[,] combination)  
  263.         {             
  264.             for (int index = 0;index < 5; index++)  
  265.             {  
  266.                 //4、綠房子在白房子左面
  267. #if FastCompute
  268.                 if (index > 0 && combination[index, 1] == "白" && combination[index - 1, 1] != "綠"returnfalse;  
  269. #else
  270.                 if (combination[index, 1] == "白")  
  271.                 {  
  272.                     for (int i = index + 1; i < 5; i++)  
  273.                     {  
  274.                         if (combination[i, 1] == "綠")  //綠房子不可能出現在白房子的右邊
  275.                             returnfalse;  
  276.                     }   
  277.                 }  
  278. #endif        
  279.                 //8、住在中間的喝牛奶
  280.                 if (combination[2, 2] != "牛奶"returnfalse;  
  281.                 //9、挪威住第一間房
  282.                 if (combination[0, 0] != "挪威"returnfalse;  
  283.                 //10、抽Blends香菸的住在養貓的隔壁
  284.                 if (combination[index, 3] == "Blends")  
  285.                 {  
  286.                     if(!((index>0 && combination[index-1,4]=="貓") || (index<4 && combination[index+1,4]=="貓")))  
  287.                     {  
  288.                          returnfalse;  
  289.                     }  
  290.                 }  
  291.                 //11、養馬住在抽Dunhill香菸的隔壁
  292.                 if (combination[index, 4] == "馬")  
  293.                 {  
  294.                     if (!((index > 0 && combination[index - 1, 3] == "Dunhill") || (index < 4 && combination[index + 1, 3] == "Dunhill")))  
  295.                     {  
  296.                         returnfalse;  
  297.                     }  
  298.                 }  
  299.                 //14、挪威住藍房子隔壁
  300.                 if (combination[index, 0] == "挪威")  
  301.                 {  
  302.                     if (!((index > 0 && combination[index - 1, 1] == "藍") || (index < 4 && combination[index + 1, 1] == "藍")))  
  303.                     {  
  304.                         returnfalse;  
  305.                     }  
  306.                 }  
  307.                 //15、抽Blends香菸的人有一個喝水的鄰居
  308.                 if (combination[index, 3] == "Blends")  
  309.                 {  
  310.                     if (!((index > 0 && combination[index - 1, 2] == "水") || (index < 4 && combination[index + 1, 2] == "水")))  
  311.                     {  
  312.                         returnfalse;  
  313.                     }  
  314.                 }  
  315.             }           
  316.             returntrue;  
  317.         }  
  318.     }  
  319. }  
//[葉帆工作室] http://blog.csdn.net/yefanqiu #define FastCompute     using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Diagnostics;    namespace Einstein{    public partial class frmMain : Form    {        public frmMain()        {            InitializeComponent();        }        private void btnRun_Click(object sender, EventArgs e)        {                                                              Arithmetic arithmetic = new Arithmetic();                  DateTime dt = DateTime.Now;            string  result = arithmetic.DoResult();            MessageBox.Show(result + "/r/n耗時:" + (DateTime.Now - dt).TotalSeconds.ToString() + "秒");        }               }    public class Arithmetic    {        string[] people   = new string[] { "英國", "瑞典", "丹麥", "挪威", "德國" };        string[] house = new string[] { "紅", "綠", "白", "黃", "藍" };        string[] drink = new string[] { "茶", "咖啡", "牛奶", "啤酒", "水" };        string[] smoke = new string[] { "Pall Mall", "Dunhill", "Blends", "Blue Master", "Prince" };        string[] pet = new string[] { "狗", "鳥", "貓", "馬", "魚" };        List<string[]> lstCombination = new List<string[]>();   //存放全部結果(預刪減後的結果)        List<string[]> lstCombination0 = new List<string[]>();        List<string[]> lstCombination1 = new List<string[]>();        List<string[]> lstCombination2 = new List<string[]>();        List<string[]> lstCombination3 = new List<string[]>();        List<string[]> lstCombination4 = new List<string[]>();                                      public string DoResult()        {            string[,] result = new string[5, 5];            //生成全部的組合            MakeCombination();            //預剔除不符合條件的組合            EliminateCombination();            //獲得有可能的組合0            EliminateCombination0();            //獲得有可能的組合1            EliminateCombination1();            //獲得有可能的組合2            EliminateCombination2();            //獲得有可能的組合3            EliminateCombination3();            //獲得有可能的組合4            EliminateCombination4();            string strInfo = "";            int intNum = 0;            for (int i = 0; i < lstCombination0.Count; i++)                {                ToCombination(result, 0, lstCombination0,i);                for (int j =0; j < lstCombination1.Count; j++)                  {                    ToCombination(result, 1, lstCombination1,j);                    for (int k = 0; k < lstCombination2.Count; k++)                     {                        ToCombination(result,  2,lstCombination2, k);                        for (int l =0; l < lstCombination3.Count; l++)                          {                            ToCombination(result,  3,lstCombination3, l);                            for (int m =0; m < lstCombination4.Count; m++)                             {                                ToCombination(result, 4,lstCombination4, m);                                bool Flag=true;                                for (int e = 0; e < 5; e++)                                {                                    if (result[0, e] == result[1, e] || result[0, e] == result[2, e] || result[0, e] == result[3, e] || result[0, e] == result[4, e] ||                                        result[1, e] == result[2, e] || result[1, e] == result[3, e] || result[1, e] == result[4, e] ||                                        result[2, e] == result[3, e] || result[2, e] == result[4, e] ||                                        result[3, e] == result[4, e])                                    {                                        Flag = false;                                        break;                                    }                                }                                  //判斷組合是否成立                                if (Flag && Judge(result))                                {                                    strInfo += "---------------- " + (++intNum).ToString()+" ----------------/r/n";                                    for (int ii = 0; ii < 5; ii++)                                    {                                        for (int jj = 0; jj < 5; jj++)                                        {                                            strInfo += result[ii, jj] + " ";                                        }                                        strInfo += "/r/n";                                    }#if FastCompute                                    strInfo += "------------------------------------/r/n";                                    return strInfo;#endif                                }                            }                        }                    }                }            }            strInfo += "------------------------------------/r/n";            return strInfo;                   }        private void ToCombination(string[,] result,int index, List<string[]>  lst,int num)        {            for (int i = 0; i < 5; i++)            {                result[index, i] = lst[num][i];            }        }        //生成全部的組合        private void MakeCombination()        {            string[] combination = new string[5];            //5*5*5*5*5=3125            for (int i = 0; i < 5; i++) //國籍            {                combination[0] = people[i];                for (int j = 0; j < 5; j++)  //房子                {                    combination[1] = house[j];                    for (int k = 0; k < 5; k++)  //飲料                    {                        combination[2] = drink[k];                        for (int l = 0; l < 5; l++)  //香菸                        {                            combination[3] = smoke[l];                            for (int m = 0; m < 5; m++)  //寵物                            {                                combination[4] = pet[m];                                lstCombination.Add((string[])combination.Clone());                            }                        }                    }                }            }        }        //剔除組合的判斷條件        private bool JudgeCombination(string[] combination)        {            //1、英國住紅房子