愛因斯坦謎題 誰養魚 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條,綠房子在白房子的左邊,是緊鄰?還是可以分開?三、第一個房子,從什麼方向開始算起,左,還是右?
如果僅把上面的第二點提到的綠房子在白房子的左邊,不限於緊鄰,則會出現
這顯然不符合愛因斯坦謎題的本意,所以又查了查英文原題,結果真相大白,其嚴謹的表述有效的消除了以上的歧義。那最終的結果究竟又如何呢?
英文原題:
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 plain copy print?- //[葉帆工作室] 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();
- }
- privatevoid 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() + "秒");
- }
- }
- publicclass Arithmetic
- {
- string[] people = newstring[] { "英國", "瑞典", "丹麥", "挪威", "德國" };
- string[] house = newstring[] { "紅", "綠", "白", "黃", "藍" };
- string[] drink = newstring[] { "茶", "咖啡", "牛奶", "啤酒", "水" };
- string[] smoke = newstring[] { "Pall Mall", "Dunhill", "Blends", "Blue Master", "Prince" };
- string[] pet = newstring[] { "狗", "鳥", "貓", "馬", "魚" };
- 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[]>();
- publicstring DoResult()
- {
- string[,] result = newstring[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;
- }
- privatevoid ToCombination(string[,] result,int index, List<string[]> lst,int num)
- {
- for (int i = 0; i < 5; i++)
- {
- result[index, i] = lst[num][i];
- }
- }
- //生成全部的組合
- privatevoid MakeCombination()
- {
- string[] combination = newstring[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());
- }
- }
- }
- }
- }
- }
- //剔除組合的判斷條件
- privatebool JudgeCombination(string[] combination)
- {
- //1、英國住紅房子
- if (combination[0] == "英國" && combination[1] != "紅") returnfalse;
- //2、瑞典養狗
- if (combination[0] == "瑞典" && combination[4] != "狗") returnfalse;
- //3、丹麥喝茶
- if (combination[0] == "丹麥" && combination[2] != "茶") returnfalse;
- //5、綠房子主喝咖啡
- if (combination[1] == "綠" && combination[2] != "咖啡") returnfalse;
- //6、抽Pall Mall香菸的養鳥
- if (combination[3] == "Pall Mall" && combination[4] != "鳥") returnfalse;
- //7、黃房子主抽Dunhill香菸
- if (combination[1] == "黃" && combination[3] != "Dunhill") returnfalse;
- //12、抽Blue Master的喝啤酒
- if (combination[3] == "Blue Master" && combination[2] != "啤酒") returnfalse;
- //13、德國抽Prince香菸
- if (combination[0] == "德國" && combination[3] != "Prince") returnfalse;
- returntrue;
- }
- //預剔除不符合條件的組合
- privatevoid EliminateCombination()
- {
- string[] combination=newstring[5];
- int num=lstCombination.Count;
- int index = 0;
- while ((num--)>0)
- {
- if (!JudgeCombination(lstCombination[index]))
- {
- lstCombination.RemoveAt(index);
- }
- else
- {
- index++;
- }
- }
- }
- //建立組合0
- privatevoid EliminateCombination0()
- {
- lstCombination0.Clear();
- foreach (string[] combination in lstCombination)
- {
- //combination[1] != "紅" && combination[1] != "藍" && combination[1] != "白" && combination[1] != "綠"
- #if FastCompute
- if (combination[0] == "挪威" && combination[1] == "黃" && combination[2] != "牛奶" && combination[2] != "茶" && combination[3] != "Prince" && combination[4] != "狗")
- #else
- if (combination[0] == "挪威" && combination[1] != "紅" && combination[1] != "藍" && combination[1] != "白" && combination[2] != "牛奶" && combination[2] != "茶" && combination[3] != "Prince" && combination[4] != "狗")
- #endif
- {
- lstCombination0.Add(combination);
- }
- }
- }
- //建立組合1
- privatevoid EliminateCombination1()
- {
- lstCombination1.Clear();
- foreach (string[] combination in lstCombination)
- {
- if (combination[0] != "挪威" && combination[1] == "藍" && combination[2] != "牛奶")
- {
- lstCombination1.Add(combination);
- }
- }
- }
- //建立組合2
- privatevoid EliminateCombination2()
- {
- lstCombination2.Clear();
- foreach (string[] combination in lstCombination)
- {
- #if FastCompute
- if (combination[0] != "挪威" && combination[0] != "丹麥" && combination[1] != "藍" && combination[1] != "黃" && combination[1] != "白" && combination[2] == "牛奶")
- #else
- if (combination[0] != "挪威" && combination[0] != "丹麥" && combination[1] != "藍" && combination[2] == "牛奶")
- #endif
- {
- lstCombination2.Add(combination);
- }
- }
- }
- //建立組合3
- privatevoid EliminateCombination3()
- {
- lstCombination3.Clear();
- foreach (string[] combination in lstCombination)
- {
- #if FastCompute
- if (combination[0] != "挪威" && combination[1] != "黃" && combination[1] != "藍" && combination[2] != "牛奶")
- #else
- if (combination[0] != "挪威" && combination[1] != "藍" && combination[2] != "牛奶")
- #endif
- {
- lstCombination3.Add(combination);
- }
- }
- }
- //建立組合4
- privatevoid EliminateCombination4()
- {
- lstCombination4.Clear();
- foreach (string[] combination in lstCombination)
- {
- #if FastCompute
- if (combination[0] != "挪威" && combination[1] != "黃" && combination[1] != "藍" && combination[1] != "綠" && combination[2] != "牛奶")
- #else
- if (combination[0] != "挪威" && combination[1] != "藍" && combination[1] != "綠" && combination[2] != "牛奶")
- #endif
- {
- lstCombination4.Add(combination);
- }
- }
- }
- //判斷
- privatestaticbool Judge(string[,] combination)
- {
- for (int index = 0;index < 5; index++)
- {
- //4、綠房子在白房子左面
- #if FastCompute
- if (index > 0 && combination[index, 1] == "白" && combination[index - 1, 1] != "綠") returnfalse;
- #else
- if (combination[index, 1] == "白")
- {
- for (int i = index + 1; i < 5; i++)
- {
- if (combination[i, 1] == "綠") //綠房子不可能出現在白房子的右邊
- returnfalse;
- }
- }
- #endif
- //8、住在中間的喝牛奶
- if (combination[2, 2] != "牛奶") returnfalse;
- //9、挪威住第一間房
- if (combination[0, 0] != "挪威") returnfalse;
- //10、抽Blends香菸的住在養貓的隔壁
- if (combination[index, 3] == "Blends")
- {
- if(!((index>0 && combination[index-1,4]=="貓") || (index<4 && combination[index+1,4]=="貓")))
- {
- returnfalse;
- }
- }
- //11、養馬住在抽Dunhill香菸的隔壁
- if (combination[index, 4] == "馬")
- {
- if (!((index > 0 && combination[index - 1, 3] == "Dunhill") || (index < 4 && combination[index + 1, 3] == "Dunhill")))
- {
- returnfalse;
- }
- }
- //14、挪威住藍房子隔壁
- if (combination[index, 0] == "挪威")
- {
- if (!((index > 0 && combination[index - 1, 1] == "藍") || (index < 4 && combination[index + 1, 1] == "藍")))
- {
- returnfalse;
- }
- }
- //15、抽Blends香菸的人有一個喝水的鄰居
- if (combination[index, 3] == "Blends")
- {
- if (!((index > 0 && combination[index - 1, 2] == "水") || (index < 4 && combination[index + 1, 2] == "水")))
- {
- returnfalse;
- }
- }
- }
- returntrue;
- }
- }
- }