愛因斯坦謎題:誰養魚(C#版)

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

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

1. 有5棟5種顏色的房子

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

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

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

已知條件:

1. 英國人住在紅房子裏

2. 瑞典人養了一條狗

3. 丹麥人喝?

4. 綠房子在白房子的左邊

5. 綠房子主人喝咖啡

6. 抽pallmall煙的人養了一隻鳥

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 adjacent(woog註釋:adjacent adj,毗連的,鄰近的,接近的;n,近鄰) to the left of the white house

The Big Question is:

Who owns the Fish?

 

CLUES:

1、The Brit lives in the red house

2、The Swede keeps dogs as pets

3、The Dane drinks tea

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

5、The green house owner drinks coffee

6、The person who smokes Pall Mall raises birds

7、The owner of the yellow house smokes Dunhill

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

9、The Norwegian lives in the first house

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

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

12、The owner who smokes Bluemaster drinks juice

13、The German smokes Prince

14、The Norwegian lives next to the blue house

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

 

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

 

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

 

最終的計算結果如下(7組結果由於不合理,故省略,有興趣的朋友可以自己把上面的代碼運行一下):

-----------------------------------

挪威 黃 水 Dunhill 貓  

丹麥 藍 茶 Blends 馬      

英國 紅 牛奶 Pall Mall 鳥

德國 綠 咖啡 Prince 魚    

瑞典 白 啤酒 Blue Master 狗  

-----------------------------------

耗時:115.15625秒

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章