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吧~
Linq编程小趣味爱因斯坦谜题的更多相关文章
- C#应用编程小例子-03-展示另一个窗体
C#应用编程小例子-03-展示另一个窗体 using System; using System.Collections.Generic; using System.ComponentModel; us ...
- C++编程小知识随手记
C++编程小知识点: (1)queue和vector类型: 加入元素 : queue是queue.push(),vector是vector.push_back(), 删除元素: queue是queue ...
- Python(五)编程小实例
Python(五)编程小实例 抓取网页信息,并生成txt文件内容! Python抓取网页技能--Python抓取网页就是我们常看见的网络爬虫,我们今天所要用到的就是我们Python中自带的模块,用这些 ...
- 在做关于NIO TCP编程小案例时遇到无法监听write的问题,没想到只是我的if语句的位置放错了位置,哎,看了半天没看出来
在做关于NIO TCP编程小案例时遇到无法监听write的问题,没想到只是我的if语句的位置放错了位置,哎,看了半天没看出来 贴下课堂笔记: 在Java中使用NIO进行网络TCP套接字编程主要以下几个 ...
- C#应用编程小例子-01-渐显的窗体
C#应用编程小例子-01-渐显的窗体 using System; using System.Windows.Forms; namespace WindowsFormsApp2 { public par ...
- Java编程小技巧(1)——方法传回两个对象
原文地址:Java编程小技巧(1)--方法传回两个对象 | Stars-One的杂货小窝 题目是个伪命题,由Java语法我们都知道,方法要么返回一个对象,要么就不返回 当有这样的情况,我们需要返回两个 ...
- Shellcode编程小技巧
工作需要,需要注入其他程序监控一些东西,检测到的数据通过WM_COPY 消息发送给显示窗体.(大体是这样的还没定稿) ##1 选择一个框架 ## tombkeeper/Shellcode_Templa ...
- hadoop编程小技巧(5)---自定义输入文件格式类InputFormat
Hadoop代码测试环境:Hadoop2.4 应用:在对数据需要进行一定条件的过滤和简单处理的时候可以使用自定义输入文件格式类. Hadoop内置的输入文件格式类有: 1)FileInputForma ...
- iOS开发之网络编程--小文件下载
文件下载方式: 如果下载的文件比较小,下载方式: 直接用NSData的 +(id)dataWithContentsOfURL:(NSURL*)url; 利用NSURLConnection发送一个HTT ...
随机推荐
- OpenCV 基础笔记
本文大部分内容来源于入门者的Python快速教程 - 番外篇之Python-OpenCV 本篇将介绍和深度学习数据处理阶段最相关的基础使用,并完成4个有趣实用的小例子: 延时摄影小程序 视频中截屏采样 ...
- Java 集合补充
集合大致可以分List,Set,Queue,Map四种体系. 集合和数组不一样,数组元素可以是基本类型的值,也可以是对象(的引用变量),集合里只能保存对象(的引用变量). 访问:如果访问List集合中 ...
- 利用过滤器对string类型的入参进行统一trim
背景 最近做的一些项目都是后台管理系统,主要是对表单数据的增删改查操作,其中有些表单项是字符串类型的,对于这些类型的表单项就需要在保存或编辑之前要进行.trim()处理,刚开始感觉没什么,遇到了就手动 ...
- JDK源码分析(四)——LinkedHashMap
目录 LinkedHashMap概述 内部字段及构造方法 存储元素 取出元素 删除元素 迭代器 利用LinkedHashMap简单实现LRU算法 总结 LinkedHashMap概述 JDK对Li ...
- 怎么将maven项目打包成war包
问题:我在eclipse上能运行,然后我想将这个maven项目打包成war然后放到另外一台机子上(其实是手动放在tomcat的webapp目录中),提供外部访问.现在问题是,一直maven项目打包一直 ...
- 简单介绍下python中函数的基础语法
python 函数 定义 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可. 特性 减少代码重复 使程序变得可扩展 使程序变得易于维护 函数的创建 pyt ...
- win32创建窗口函数(windows程序内部运行机制)
利用win32创建窗口函数,主要操作步骤为: 1.设计一个窗口类 2.注册窗口类 3.创建窗口 4.显示及窗口更新 5.消息循环 6.窗口过程函数 (1)设计一个窗口类 设计窗口类,这样的类型已经 ...
- ngx_lua配置及应用
一.说明 这里不对lua语言本身及其编译器运行环境等做介绍,以下所有介绍前提对lua相关有所了解. 二.ngx_lua介绍 原理 ngx_lua将Lua嵌入Nginx,可以让Nginx执行Lua脚本, ...
- chinese hacker-----WriteUp
原题地址:http://ctf5.shiyanbar.com/web/2/ 提示下载一个数据库 下载下来后发现是加密的 有密码,但发现密码不是4648 这里用到“DbView” 直接破解密码进入 发 ...
- wikioi 1078 最小生成树 Kruskal算法
1078 最小生成树 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 白银 Silver 题目描述 Description 农民约翰被选为他们镇的镇长!他其中一个竞选承诺 ...