Linq編程小趣味愛因斯坦謎題


最近看到一個比較老的題目,題目----在一條街上,有5座房子,噴了5種顏色,每個房里住着不同國籍的人,每個人喝不同的飲料,抽不同品牌的香煙,養不同的寵物,問題---誰養魚?

以前沒事還做過這個題,現在寫個代碼實現一下,還是感覺還是挺有意思的,先來看下推導條件吧:

    1.英國人住紅色房子 
    2.瑞典人養狗 
    3.丹麥人喝茶 
    4.綠色房子在白色房子左面 
    5.綠色房子主人喝咖啡 
    6.抽Pall Mall 香煙的人養鳥 
    7.黃色房子主人抽Dunhill 香煙 
    8.住在中間房子的人喝牛奶 
    9. 挪威人住第一間房 
    10.抽Blends香煙的人住在養貓的人隔壁 
    11.養馬的人住抽Dunhill 香煙的人隔壁 
    12.抽Blue Master的人喝啤酒 
    13.德國人抽Prince香煙 
    14.挪威人住藍色房子隔壁 
    15.抽Blends香煙的人有一個喝水的鄰居

人工推導

自己開始做的時候在本子上推導的,就是畫畫改改,本來想拍圖片的,這樣就不用費勁了,鑒於本人字體需要提高,還是重新弄了幾張圖上來,簡單說下推導過程:

1選擇確定條件和不確定條件:

不確定條件: 4.綠色房子在白色房子左面 ;  8.住在中間房子的人喝牛奶 ; 9. 挪威人住第一間房;  10.抽Blends香煙的人住在養貓的人隔壁;11.養馬的人住抽Dunhill 香煙的人隔壁 ;   14.挪威人住藍色房子隔壁 ;15.抽Blends香煙的人有一個喝水的鄰居
(特別說明:條件9和14算是確定條件,一號房是挪威人住,二號房是藍色,不用畫圖,也不用推導,直接可以得出的結論,放在不確定里面是因為不好在確定條件里面展示)

2.條件推導

推導的步驟  8,9,14(二號房是藍色)→4,5(四號房是綠色,五號房是白色)→1,7(一號房是黃色,三號房是紅色)→11(二號房養馬),最后推導出的結果圖如下:

 

3.這個時候剩下的條件:2,3,6,10,12,13,15,自己推導的時候在這里困擾了一下,像填字游戲一樣,條件怎么弄進去感覺都是對的,觀察了最后剩下的三種飲料:啤酒, 茶,水,而且給出的條件比較多,3,12,15,條件3丹麥人喝茶,適用范圍是二號房和五號房,假設丹麥人是五號房(走不通),丹麥人是二號房,接下來的事情就比較容易推導.(3,12,10,15,13,2,6==本人按照這個順序推導的)

 

程序推導   

1.根據題目,創建一個包含房號,國家,顏色,飲料,寵物,香煙的Person類:

   public class Person
    {
        //房號
        public int Position { get; set; }
        //國家
        public string Country { get; set; }
        //房子顏色
        public string Color { get; set; }
        //飲料
        public string Drink { get; set; }
        //香煙
        public string Cigarette { get; set; }
        //寵物
        public string Animal { get; set; }
    }

2.去除所有的確定選項:

   int[] indexArr = new int[] { 1, 2, 3, 4, 5 };
            string[] countryArr = new string[] { "瑞典", "德國", "英國", "丹麥", "挪威" };
            string[] colorArr = new string[] { "黃色", "藍色", "紅色", "綠色", "白色" };
            string[] drinkArr = new string[] { "水", "茶", "牛奶", "咖啡", "啤酒" };
            string[] cigareteeArr = new string[] { "Pall Mall", "Dunhill", "Blends", "Blue Master", "Prince" };
            string[] animalArr = new string[] { "貓", "馬", "鳥", "魚", "狗" };
            Stopwatch stopWatch = new Stopwatch();
            stopWatch.Start();
            var allData = (from index in indexArr
                           from country in countryArr
                           from color in colorArr
                           from drink in drinkArr
                           from cigaretee in cigareteeArr
                           from animal in animalArr
                           select new Person { Position = index, Country = country, Color = color, Drink = drink, Cigarette = cigaretee, Animal = animal }).ToList();
            //1.英國人住紅色房子
            allData.RemoveAll(p => p.Country == "英國" && p.Color != "紅色");
            allData.RemoveAll(p => p.Country != "英國" && p.Color == "紅色");

            // 2.瑞典人養狗
            allData.RemoveAll(p => p.Country == "瑞典" && p.Animal != "狗");
            allData.RemoveAll(p => p.Country != "瑞典" && p.Animal == "狗");

            // 3.丹麥人喝茶
            allData.RemoveAll(p => p.Country == "丹麥" && p.Drink != "茶");
            allData.RemoveAll(p => p.Country != "丹麥" && p.Drink == "茶");

            // 5.綠色房子主人喝咖啡
            allData.RemoveAll(p => p.Color == "綠色" && p.Drink != "咖啡");
            allData.RemoveAll(p => p.Color != "綠色" && p.Drink == "咖啡");

            // 6.抽Pall Mall 香煙的人養鳥
            allData.RemoveAll(p => p.Cigarette == "Pall Mall" && p.Animal != "鳥");
            allData.RemoveAll(p => p.Cigarette != "Pall Mall" && p.Animal == "鳥");

            //7.黃色房子主人抽Dunhill 香煙
            allData.RemoveAll(p => p.Color == "黃色" && p.Cigarette != "Dunhill");
            allData.RemoveAll(p => p.Color != "黃色" && p.Cigarette == "Dunhill");

            //8.挪威人住第一間房
            allData.RemoveAll(p => p.Country == "挪威" && p.Position != 1);
            allData.RemoveAll(p => p.Country != "挪威" && p.Position == 1);

            //9.挪威人住第一間房
            allData.RemoveAll(p => p.Drink == "牛奶" && p.Position != 3);
            allData.RemoveAll(p => p.Drink != "牛奶" && p.Position == 3);

            //12.抽Blue Master的人喝啤酒
            allData.RemoveAll(p => p.Drink == "啤酒" && p.Cigarette != "Blue Master");
            allData.RemoveAll(p => p.Drink != "啤酒" && p.Cigarette == "Blue Master");
            //13.德國人抽Prince香煙
            allData.RemoveAll(p => p.Country == "德國" && p.Cigarette != "Prince");
            allData.RemoveAll(p => p.Country != "德國" && p.Cigarette == "Prince");

            // 14.挪威人住藍色房子隔壁(藍色房子是二號房)
            allData.RemoveAll(p => p.Color == "藍色" && p.Position != 2);
            allData.RemoveAll(p => p.Color != "藍色" && p.Position == 2);

 3.窮舉取出所有的可能的結果集(一組對象,不是一個對象)

            var result = (from r1 in allData.Where(item => item.Position == 1)
                          from r2 in allData.Where(item => item.Position == 2)
                          from r3 in allData.Where(item => item.Position == 3)
                          from r4 in allData.Where(item => item.Position == 4)
                          from r5 in allData.Where(item => item.Position == 5)
                          where r1.Country != r2.Country && r1.Country != r3.Country && r1.Country != r4.Country && r1.Country != r5.Country &&
                                r2.Country != r3.Country && r2.Country != r4.Country && r2.Country != r5.Country &&
                                r3.Country != r4.Country && r3.Country != r5.Country &&
                                r4.Country != r5.Country &&
                                r1.Color != r2.Color && r1.Color != r3.Color && r1.Color != r4.Color && r1.Color != r5.Color &&
                                r2.Color != r3.Color && r2.Color != r4.Color && r2.Color != r5.Color &&
                                r3.Color != r4.Color && r3.Color != r5.Color &&
                                r4.Color != r5.Color &&
                                r1.Drink != r2.Drink && r1.Drink != r3.Drink && r1.Drink != r4.Drink && r1.Drink != r5.Drink &&
                                r2.Drink != r3.Drink && r2.Drink != r4.Drink && r2.Drink != r5.Drink &&
                                r3.Drink != r4.Drink && r3.Drink != r5.Drink &&
                                r4.Drink != r5.Drink &&
                                r1.Cigarette != r2.Cigarette && r1.Cigarette != r3.Cigarette && r1.Cigarette != r4.Cigarette && r1.Cigarette != r5.Cigarette &&
                                r2.Cigarette != r3.Cigarette && r2.Cigarette != r4.Cigarette && r2.Cigarette != r5.Cigarette &&
                                r3.Cigarette != r4.Cigarette && r3.Cigarette != r5.Cigarette &&
                                r4.Cigarette != r5.Cigarette &&
                                r1.Animal != r2.Animal && r1.Animal != r3.Animal && r1.Animal != r4.Animal && r1.Animal != r5.Animal &&
                                r2.Animal != r3.Animal && r2.Animal != r4.Animal && r2.Animal != r5.Animal &&
                                r3.Animal != r4.Animal && r3.Animal != r5.Animal &&
                                r4.Animal != r5.Animal
                          select new List<Person> { r1, r2, r3, r4, r5 }).ToList();

4.按照剩余的條件進行刪除並輸出:

            // 4.綠色房子在白色房子左面
            //白色房子的房號比綠色的大1
            result.RemoveAll(item => 1 != item.Single(m => m.Color == "白色").Position - item.Single(m => m.Color == "綠色").Position);
        
             // 10.抽Blends香煙的人住在養貓的人隔壁
            result.RemoveAll(item => 1 != Math.Abs(item.Single(m => m.Cigarette == "Blends").Position - item.Single(m => m.Animal == "貓").Position));
            //  11.養馬的人住抽Dunhill 香煙的人隔壁
            result.RemoveAll(item => 1 != Math.Abs(item.Single(m => m.Animal == "馬").Position - item.Single(m => m.Cigarette == "Dunhill").Position));
            //14.挪威人住藍色房子隔壁(藍色房子是二號房)
            //result.RemoveAll(item => 1 != Math.Abs(item.Single(m => m.Country == "挪威").Position - item.Single(m => m.Color == "藍色").Position));
            //15.抽Blends香煙的人有一個喝水的鄰居
            result.RemoveAll(item => 1 != Math.Abs(item.Single(m => m.Cigarette == "Blends").Position - item.Single(m => m.Drink == "水").Position));

            var person = result.Select(item => item.Single(m => m.Animal == "魚")).First();
            stopWatch.Stop();
            TimeSpan ts = stopWatch.Elapsed;
            string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
                ts.Hours, ts.Minutes, ts.Seconds,
                ts.Milliseconds / 10);
            Console.WriteLine("{0},時間:{1}", person.Country, elapsedTime.ToString());
            Console.WriteLine("編號\0\0國家\0\0顏色\0\0飲料\0\0寵物\0\0香煙");
            foreach (var item in result)
            {
                foreach (Person data in item)
                {
                    if (data.Position == 1 || data.Position == 2)
                    {
                        Console.WriteLine("\0{0}\0\0\0\0{1}\0\0{2}\0\0{3}\0\0\0\0{4}\0\0\0{5}", data.Position, data.Country, data.Color, data.Drink, data.Animal, data.Cigarette);
                    }
                    else
                    {
                        Console.WriteLine("\0{0}\0\0\0\0{1}\0\0{2}\0\0{3}\0\0{4}\0\0\0{5}", data.Position, data.Country, data.Color, data.Drink, data.Animal, data.Cigarette);
                    }
                }
            }
            Console.Read();

  

小結

兩種推導的方式思維其實還蠻不一樣的,相對來說人工的需要自己的去按照自己經驗,知識,去做出一些判斷,在一些難點有自己的一套解決思路,比如說條件3丹麥人喝茶在自己推導的時候是一個難點,而在寫程序的時候直接刪除這種可能即可,寫程序的時候我們需要先窮舉出所有可能,就是很長的where語句那塊,這一階段弄明白了,應該都很明了。屬於自己無意中看到的一個題目,屬於編程的小樂趣吧,也可以算是Linq入門的一個小Demo吧~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM