最近看到一个比较老的题目,题目----在一条街上,有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吧~

Linq编程小趣味爱因斯坦谜题的更多相关文章

  1. C#应用编程小例子-03-展示另一个窗体

    C#应用编程小例子-03-展示另一个窗体 using System; using System.Collections.Generic; using System.ComponentModel; us ...

  2. C++编程小知识随手记

    C++编程小知识点: (1)queue和vector类型: 加入元素 : queue是queue.push(),vector是vector.push_back(), 删除元素: queue是queue ...

  3. Python(五)编程小实例

    Python(五)编程小实例 抓取网页信息,并生成txt文件内容! Python抓取网页技能--Python抓取网页就是我们常看见的网络爬虫,我们今天所要用到的就是我们Python中自带的模块,用这些 ...

  4. 在做关于NIO TCP编程小案例时遇到无法监听write的问题,没想到只是我的if语句的位置放错了位置,哎,看了半天没看出来

    在做关于NIO TCP编程小案例时遇到无法监听write的问题,没想到只是我的if语句的位置放错了位置,哎,看了半天没看出来 贴下课堂笔记: 在Java中使用NIO进行网络TCP套接字编程主要以下几个 ...

  5. C#应用编程小例子-01-渐显的窗体

    C#应用编程小例子-01-渐显的窗体 using System; using System.Windows.Forms; namespace WindowsFormsApp2 { public par ...

  6. Java编程小技巧(1)——方法传回两个对象

    原文地址:Java编程小技巧(1)--方法传回两个对象 | Stars-One的杂货小窝 题目是个伪命题,由Java语法我们都知道,方法要么返回一个对象,要么就不返回 当有这样的情况,我们需要返回两个 ...

  7. Shellcode编程小技巧

    工作需要,需要注入其他程序监控一些东西,检测到的数据通过WM_COPY 消息发送给显示窗体.(大体是这样的还没定稿) ##1 选择一个框架 ## tombkeeper/Shellcode_Templa ...

  8. hadoop编程小技巧(5)---自定义输入文件格式类InputFormat

    Hadoop代码测试环境:Hadoop2.4 应用:在对数据需要进行一定条件的过滤和简单处理的时候可以使用自定义输入文件格式类. Hadoop内置的输入文件格式类有: 1)FileInputForma ...

  9. iOS开发之网络编程--小文件下载

    文件下载方式: 如果下载的文件比较小,下载方式: 直接用NSData的 +(id)dataWithContentsOfURL:(NSURL*)url; 利用NSURLConnection发送一个HTT ...

随机推荐

  1. Android消息总线的演进之路:用LiveDataBus替代RxBus、EventBus

    背景 对于Android系统来说,消息传递是最基本的组件,每一个App内的不同页面,不同组件都在进行消息传递.消息传递既可以用于Android四大组件之间的通信,也可用于异步线程和主线程之间的通信.对 ...

  2. Python 递归删除非空目录(包括子目录以及文件)

    Python的OS模块自带rmdir和removedirs函数用于删除目录,但是两者都不能删除非空目录,以下代码定义了一个函数 remove_dir 用于删除非空目录. #作者官网 http://ww ...

  3. 出现报错: module build failed error couldn't find preset es2015 relative to directory

    当用webpack 进行 build 的时候, 会出现如上标题的错误, 解决方式是在 上级 或者 上上级目录,删除 .babelrc 文件

  4. win 10 文件夹 背景 没效果

    韩梦飞沙 yue31313 韩亚飞 han_meng_fei_sha  313134555@qq.com

  5. [BZOJ4699]树上的最短路(最短路+线段树)

    https://www.cnblogs.com/Gloid/p/10273902.html 这篇文章已经从头到尾讲的非常清楚了,几乎没有什么需要补充的内容. 首先$O(n\log^2 n)$的做法比较 ...

  6. hdu 2112 最短路

    本来是拿来复习一下map的,没想搞了半天,一直wa,最后发现预处理没有处理到所有的点 就是个最短路 Sample Input 6 xiasha westlake xiasha station 60 x ...

  7. Codeforces Round #257 (Div. 2) C. Jzzhu and Chocolate

    C. Jzzhu and Chocolate time limit per test 1 second memory limit per test 256 megabytes input standa ...

  8. ZOJ 2969 Easy Task

    E - Easy Task Description Calculating the derivation of a polynomial is an easy task. Given a functi ...

  9. Redis在Windows+linux平台下的安装配置(转)

    window平台Redis安装 下载地址: http://code.google.com/p/servicestack/wiki/RedisWindowsDownload Redis文件夹有以下几个文 ...

  10. C++中使用REST操作

    REST现在是非常流行的一种接口了,但对于C++这种古董语言来说,用起来并不很方便.无论是json操作还是http交互,用起来都比较麻烦. 如果你需要在c++中使用rest操作时,不妨试一下微软的cp ...