LINQ解 爱因斯坦迷题

据说是爱因斯坦迷题,不知是真是假,不过这道集合运算的题还是挺有意思的,比一般的[谁是凶手]的题多了集合项之间的关系
用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;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    
class Program
    
{
        
static void Main(string[] args)
        
{
            
//--------------------------1阶段----------------------------------------------
            int[] 房子位置 = new int[] 12345 };
            
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}", 房子位置, 房子颜色, 国籍, 宠物, 饮品, 香烟);
        }


    }

}


结果

posted @ 2008-01-14 10:57  WXWinter(冬)  阅读(4980)  评论(18编辑  收藏  举报