原文地址:http://www.cnblogs.com/foundation/archive/2008/01/14/1037907.html
据说是爱因斯坦迷题,不知是真是假,不过这道集合运算的题还是挺有意思的,比一般的[谁是凶手]的题多了集合项之间的关系
用linq的集合运算符,不用if、for等控制流语句解一下这道题.
本题的解题方式用的是工作流处理问题的方式
将事项分为阶段(也叫状态),每个阶段按一定顺连接,每个阶段内由处理该阶段问题的一组业务结点组成,业务结点的添加或移除不影响处理问题的架构
还有,业务结点最好是真正真实业务的映射,最好不要出现
[ 8、挪威人住第一间房 ]+ [14、挪威人住蓝色房子隔壁],推出[第2间房子是蓝色]的业务结点,要推也得由系统推(这叫反映链),而不能由开发人员推,这样就可以在架构完成后随意修改业务结点,本例用的就是这种方式,由于没有人工推理加入,执行效率有些低,
在Core2 Duo CPU 7300上,用 System.Diagnostics.Stopwatch
Debug 模式下用时:06.5122712
Release 模式下用时:05.2872722
问题:
在一条街上,有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香烟的人有一个喝水的邻居
代码
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
//--------------------------1阶段----------------------------------------------
int[] 房子位置 = new int[] { 1, 2, 3, 4, 5 };
string[] 房子颜色 = new string[] { "黄", "蓝", "红", "绿", "白" };
string[] 国籍 = new string[] { "挪威", "丹麦", "英国", "德国", "瑞典" };
string[] 宠物 = new string[] { "猫", "马", "鸟", "鱼", "狗" };
string[] 饮品 = new string[] { "水", "茶", "牛奶", "咖啡", "啤酒" };
string[] 香烟 = new string[] { "Dunhill", "Blends", "Pall Mall", "Prince", "Blue Master" };
var v = (from t1 in 房子位置
from t2 in 房子颜色
from t3 in 国籍
from t4 in 宠物
from t5 in 饮品
from t6 in 香烟
select new a { 房子位置 = t1, 房子颜色 = t2, 国籍 = t3, 宠物 = t4, 饮品 = t5, 香烟 = t6 }).ToList();
//------------------------2阶段-------------------------------------------------
//1、英国人住红色房子
v.RemoveAll(p => p.国籍 == "英国" && p.房子颜色 != "红");
v.RemoveAll(p => p.国籍 != "英国" && p.房子颜色 == "红");
//2、瑞典人养狗
v.RemoveAll(p => p.国籍 == "瑞典" && p.宠物 != "狗");
v.RemoveAll(p => p.国籍 != "瑞典" && p.宠物 == "狗");
//3、丹麦人喝茶
v.RemoveAll(p => p.国籍 == "丹麦" && p.饮品 != "茶");
v.RemoveAll(p => p.国籍 != "丹麦" && p.饮品 == "茶");
//5、绿色房子主人喝咖啡
v.RemoveAll(p => p.房子颜色 == "绿" && p.饮品 != "咖啡");
v.RemoveAll(p => p.房子颜色 != "绿" && p.饮品 == "咖啡");
//6、抽Pall Mall 香烟的人养鸟
v.RemoveAll(p => p.香烟 == "Pall Mall" && p.宠物 != "鸟");
v.RemoveAll(p => p.香烟 != "Pall Mall" && p.宠物 == "鸟");
//7、黄色房子主人抽Dunhill 香烟
v.RemoveAll(p => p.房子颜色 == "黄" && p.香烟 != "Dunhill");
v.RemoveAll(p => p.房子颜色 != "黄" && p.香烟 == "Dunhill");
//8、挪威人住第一间房
v.RemoveAll(p => p.国籍 == "挪威" && p.房子位置 != 1);
v.RemoveAll(p => p.国籍 != "挪威" && p.房子位置 == 1);
//9、住在中间房子的人喝牛奶
v.RemoveAll(p => p.房子位置 == 3 && p.饮品 != "牛奶");
v.RemoveAll(p => p.房子位置 != 3 && p.饮品 == "牛奶");
//12、抽Blue Master的人喝啤酒
v.RemoveAll(p => p.香烟 == "Blue Master" && p.饮品 != "啤酒");
v.RemoveAll(p => p.香烟 != "Blue Master" && p.饮品 == "啤酒");
//13、德国人抽Prince香烟
v.RemoveAll(p => p.国籍 == "德国" && p.香烟 != "Prince");
v.RemoveAll(p => p.国籍 != "德国" && p.香烟 == "Prince");
//-------------------------3阶段------------------------------------------------
//喷不同颜色,住不同国籍的人,喝不同的饮料,抽不同品牌的香烟,养不同的宠物
var vv = (from g1 in v.Where(p => p.房子位置 == 1)
from g2 in v.Where(p => p.房子位置 == 2)
from g3 in v.Where(p => p.房子位置 == 3)
from g4 in v.Where(p => p.房子位置 == 4)
from g5 in v.Where(p => p.房子位置 == 5)
where g1.饮品 != g2.饮品 && g1.饮品 != g3.饮品 && g1.饮品 != g4.饮品 && g1.饮品 != g5.饮品 &&
g2.饮品 != g3.饮品 && g2.饮品 != g4.饮品 && g2.饮品 != g5.饮品 &&
g3.饮品 != g4.饮品 && g3.饮品 != g5.饮品 &&
g4.饮品 != g5.饮品 &&
g1.宠物 != g2.宠物 && g1.宠物 != g3.宠物 && g1.宠物 != g4.宠物 && g1.宠物 != g5.宠物 &&
g2.宠物 != g3.宠物 && g2.宠物 != g4.宠物 && g2.宠物 != g5.宠物 &&
g3.宠物 != g4.宠物 && g3.宠物 != g5.宠物 &&
g4.宠物 != g5.宠物 &&
g1.国籍 != g2.国籍 && g1.国籍 != g3.国籍 && g1.国籍 != g4.国籍 && g1.国籍 != g5.国籍 &&
g2.国籍 != g3.国籍 && g2.国籍 != g4.国籍 && g2.国籍 != g5.国籍 &&
g3.国籍 != g4.国籍 && g3.国籍 != g5.国籍 &&
g4.国籍 != g5.国籍 &&
g1.香烟 != g2.香烟 && g1.香烟 != g3.香烟 && g1.香烟 != g4.香烟 && g1.香烟 != g5.香烟 &&
g2.香烟 != g3.香烟 && g2.香烟 != g4.香烟 && g2.香烟 != g5.香烟 &&
g3.香烟 != g4.香烟 && g3.香烟 != g5.香烟 &&
g4.香烟 != g5.香烟 &&
g1.房子颜色 != g2.房子颜色 && g1.房子颜色 != g3.房子颜色 && g1.房子颜色 != g4.房子颜色 && g1.房子颜色 != g5.房子颜色 &&
g2.房子颜色 != g3.房子颜色 && g2.房子颜色 != g4.房子颜色 && g2.房子颜色 != g5.房子颜色 &&
g3.房子颜色 != g4.房子颜色 && g3.房子颜色 != g5.房子颜色 &&
g4.房子颜色 != g5.房子颜色 &&
g1.房子位置 != g2.房子位置 && g1.房子位置 != g3.房子位置 && g1.房子位置 != g4.房子位置 && g1.房子位置 != g5.房子位置 &&
g2.房子位置 != g3.房子位置 && g2.房子位置 != g4.房子位置 && g2.房子位置 != g5.房子位置 &&
g3.房子位置 != g4.房子位置 && g3.房子位置 != g5.房子位置 &&
g4.房子位置 != g5.房子位置
select new List<a> { g1, g2, g3, g4, g5 }).ToList();
//------------------------4阶段-------------------------------------------------
// 4、绿色房子在白色房子左面
//(绿房子.房子位置房子 - 白.房子位置) == -1 表示左面
vv.RemoveAll(pp => -1 != pp.Single(p => p.房子颜色 == "绿").房子位置 - pp.Single(p => p.房子颜色 == "白").房子位置);
//10、抽Blends香烟的人住在养猫的人隔壁
// Abc(Blends香烟的人.房子位置 - 养猫.房子位置) == 1 表示是隔壁
vv.RemoveAll(pp => 1 != System.Math.Abs(pp.Single(p => p.宠物 == "猫").房子位置 - pp.Single(p => p.香烟 == "Blends").房子位置));
//11、养马的人住抽Dunhill 香烟的人隔壁
vv.RemoveAll(pp => 1 != System.Math.Abs(pp.Single(p => p.宠物 == "马").房子位置 - pp.Single(p => p.香烟 == "Dunhill").房子位置));
//14、挪威人住蓝色房子隔壁
vv.RemoveAll(pp => 1 != System.Math.Abs(pp.Single(p => p.国籍 == "挪威").房子位置 - pp.Single(p => p.房子颜色 == "蓝").房子位置));
//15、抽Blends香烟的人有一个喝水的邻居
vv.RemoveAll(pp => 1 != System.Math.Abs(pp.Single(p => p.香烟 == "Blends").房子位置 - pp.Single(p => p.饮品 == "水").房子位置));
//--------------------------5阶段-----------------------------------------------
//问题是:谁养鱼?
var who= vv.Select(pp => pp.Single(p => p.宠物 == "鱼"));
who.ToList().ForEach(p => System.Console.WriteLine("养鱼:{0}",p));
System.Console.WriteLine("结构:");
vv.ForEach(p=>p.ForEach(pp=>System.Console.WriteLine(pp)));
//------------------------------------------------------------------------
System.Console.Read();
}
}
class a
{
public int 房子位置;
public string 房子颜色;
public string 国籍;
public string 宠物;
public string 饮品;
public string 香烟;
public override string ToString()
{
return string.Format("{0},{1},{2},{3},{4},{5}", 房子位置, 房子颜色, 国籍, 宠物, 饮品, 香烟);
}
}
}
结果