• 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("编号国家颜色饮料宠物香烟");
                foreach (var item in result)
                {
                    foreach (Person data in item)
                    {
                        if (data.Position == 1 || data.Position == 2)
                        {
                            Console.WriteLine("{0}{1}{2}{3}{4}{5}", data.Position, data.Country, data.Color, data.Drink, data.Animal, data.Cigarette);
                        }
                        else
                        {
                            Console.WriteLine("{0}{1}{2}{3}{4}{5}", data.Position, data.Country, data.Color, data.Drink, data.Animal, data.Cigarette);
                        }
                    }
                }
                Console.Read();
    

      

    小结

    两种推导的方式思维其实还蛮不一样的,相对来说人工的需要自己的去按照自己经验,知识,去做出一些判断,在一些难点有自己的一套解决思路,比如说条件3丹麦人喝茶在自己推导的时候是一个难点,而在写程序的时候直接删除这种可能即可,写程序的时候我们需要先穷举出所有可能,就是很长的where语句那块,这一阶段弄明白了,应该都很明了。属于自己无意中看到的一个题目,属于编程的小乐趣吧,也可以算是Linq入门的一个小Demo吧~

  • 相关阅读:
    Eclipse/STS 常用快捷键
    Git代码管理常用命令
    Git命令
    Atom python版本的切换
    robot Frame之文件上传和下载
    ride打开后,log和report置灰的解决办法
    Python2和Python3共存下使用robotframework
    selenium+python
    firefox上安装selenium ide失败
    软件测试知识点补充1
  • 原文地址:https://www.cnblogs.com/xiaofeixiang/p/3962452.html
Copyright © 2020-2023  润新知