思路:一共4个数字,共需要3个运算符,可以构造一个二叉树,没有子节点的节点的为值,有叶子节点的为运算符

例如数字{1, 2, 3, 4},其中一种解的二叉树形式如下所示:

因此可以遍历所有二叉树可能的形式,4个数的全排列,从4种运算符中挑选3种运算符(运算符可以重复)

核心步骤1:需要遍历所有二叉树的可能,参考Eric Lippert的方法

  1. class Node
  2. {
  3. public Node Left { get; private set; }
  4. public Node Right { get; private set; }
  5. public Node(Node left, Node right)
  6. {
  7. this.Left = left;
  8. this.Right = right;
  9. }
  10. }
  11.  
  12. static IEnumerable<Node> AllBinaryTrees(int size)
  13. {
  14. if (size == )
  15. return new Node[] { null };
  16. return from i in Enumerable.Range(, size)
  17. from left in AllBinaryTrees(i)
  18. from right in AllBinaryTrees(size - - i)
  19. select new Node(left, right);
  20. }

核心步骤2:对于任意一个二叉树,构造表达式树

  1. static Expression Build(Node node, List<double> numbers, List<Func<Expression, Expression, BinaryExpression>> operators)
  2. {
  3. var iNum = ;
  4. var iOprt = ;
  5.  
  6. Func<Node, Expression> f = null;
  7. f = n =>
  8. {
  9. Expression exp;
  10. if (n == null)
  11. exp = Expression.Constant(numbers[iNum++]);
  12. else
  13. {
  14. var left = f(n.Left);
  15. var right = f(n.Right);
  16. exp = operators[iOprt++](left, right);
  17. }
  18. return exp;
  19. };
  20. return f(node);
  21. }

核心步骤3:遍历4个数字的全排列,全排列参考这里

  1. static IEnumerable<List<T>> FullPermute<T>(List<T> elements)
  2. {
  3. if (elements.Count == )
  4. return EnumerableOfOneElement(elements);
  5.  
  6. IEnumerable<List<T>> result = null;
  7. foreach (T first in elements)
  8. {
  9. List<T> remaining = elements.ToArray().ToList();
  10. remaining.Remove(first);
  11. IEnumerable<List<T>> fullPermuteOfRemaining = FullPermute(remaining);
  12.  
  13. foreach (List<T> permute in fullPermuteOfRemaining)
  14. {
  15. var arr = new List<T> { first };
  16. arr.AddRange(permute);
  17.  
  18. var seq = EnumerableOfOneElement(arr);
  19. if (result == null)
  20. result = seq;
  21. else
  22. result = result.Union(seq);
  23. }
  24. }
  25. return result;
  26. }
  27.  
  28. static IEnumerable<T> EnumerableOfOneElement<T>(T element)
  29. {
  30. yield return element;
  31. }

例如有四个数字{1, 2, 3, 4},它的全排列如下:

  1. , , ,
  2. , , ,
  3. , , ,
  4. , , ,
  5. , , ,
  6. , , ,
  7. , , ,
  8. , , ,
  9. , , ,
  10. , , ,
  11. , , ,
  12. , , ,
  13. , , ,
  14. , , ,
  15. , , ,
  16. , , ,
  17. , , ,
  18. , , ,
  19. , , ,
  20. , , ,
  21. , , ,
  22. , , ,
  23. , , ,
  24. , , ,

核心步骤4:从4种运算符中挑选3个运算符

  1. static IEnumerable<IEnumerable<Func<Expression, Expression, BinaryExpression>>> OperatorPermute(List<Func<Expression, Expression, BinaryExpression>> operators)
  2. {
  3. return from operator1 in operators
  4. from operator2 in operators
  5. from operator3 in operators
  6. select new[] { operator1, operator2, operator3 };
  7. }

最后是Main函数:

  1. static void Main(string[] args)
  2. {
  3. List<double> numbers = new List<double> { , , , };
  4. var operators = new List<Func<Expression, Expression, BinaryExpression>> {
  5. Expression.Add,Expression.Subtract,Expression.Multiply,Expression.Divide
  6. };
  7.  
  8. foreach (var operatorCombination in OperatorPermute(operators))
  9. {
  10. foreach (Node node in AllBinaryTrees())
  11. {
  12. foreach (List<double> permuteOfNumbers in FullPermute(numbers))
  13. {
  14. Expression expression = Build(node, permuteOfNumbers, operatorCombination.ToList());
  15. Func<double> compiled = Expression.Lambda<Func<double>>(expression).Compile();
  16. try
  17. {
  18. var value = compiled();
  19. if (Math.Abs(value - ) < 0.01)
  20. Console.WriteLine("{0} = {1}", expression, value);
  21. }
  22. catch (DivideByZeroException) { }
  23. }
  24. }
  25. }
  26. Console.Read();
  27. }

计算结果:

  1. ( * ( + ( + ))) =
  2. ( * ( + ( + ))) =
  3. ( * ( + ( + ))) =
  4. ( * ( + ( + ))) =
  5. ( * ( + ( + ))) =
  6. ( * ( + ( + ))) =
  7. ( * (( + ) + )) =
  8. ( * (( + ) + )) =
  9. ( * (( + ) + )) =
  10. ( * (( + ) + )) =
  11. ( * (( + ) + )) =
  12. ( * (( + ) + )) =
  13. (( + ) * ( + )) =
  14. (( + ) * ( + )) =
  15. (( + ) * ( + )) =
  16. (( + ) * ( + )) =
  17. (( + ) * ( + )) =
  18. (( + ) * ( + )) =
  19. (( + ) * ( + )) =
  20. (( + ) * ( + )) =
  21. (( + ( + )) * ) =
  22. (( + ( + )) * ) =
  23. (( + ( + )) * ) =
  24. (( + ( + )) * ) =
  25. (( + ( + )) * ) =
  26. (( + ( + )) * ) =
  27. ((( + ) + ) * ) =
  28. ((( + ) + ) * ) =
  29. ((( + ) + ) * ) =
  30. ((( + ) + ) * ) =
  31. ((( + ) + ) * ) =
  32. ((( + ) + ) * ) =
  33. ( * ( * ( * ))) =
  34. ( * ( * ( * ))) =
  35. ( * ( * ( * ))) =
  36. ( * ( * ( * ))) =
  37. ( * ( * ( * ))) =
  38. ( * ( * ( * ))) =
  39. ( * ( * ( * ))) =
  40. ( * ( * ( * ))) =
  41. ( * ( * ( * ))) =
  42. ( * ( * ( * ))) =
  43. ( * ( * ( * ))) =
  44. ( * ( * ( * ))) =
  45. ( * ( * ( * ))) =
  46. ( * ( * ( * ))) =
  47. ( * ( * ( * ))) =
  48. ( * ( * ( * ))) =
  49. ( * ( * ( * ))) =
  50. ( * ( * ( * ))) =
  51. ( * ( * ( * ))) =
  52. ( * ( * ( * ))) =
  53. ( * ( * ( * ))) =
  54. ( * ( * ( * ))) =
  55. ( * ( * ( * ))) =
  56. ( * ( * ( * ))) =
  57. ( * (( * ) * )) =
  58. ( * (( * ) * )) =
  59. ( * (( * ) * )) =
  60. ( * (( * ) * )) =
  61. ( * (( * ) * )) =
  62. ( * (( * ) * )) =
  63. ( * (( * ) * )) =
  64. ( * (( * ) * )) =
  65. ( * (( * ) * )) =
  66. ( * (( * ) * )) =
  67. ( * (( * ) * )) =
  68. ( * (( * ) * )) =
  69. ( * (( * ) * )) =
  70. ( * (( * ) * )) =
  71. ( * (( * ) * )) =
  72. ( * (( * ) * )) =
  73. ( * (( * ) * )) =
  74. ( * (( * ) * )) =
  75. ( * (( * ) * )) =
  76. ( * (( * ) * )) =
  77. ( * (( * ) * )) =
  78. ( * (( * ) * )) =
  79. ( * (( * ) * )) =
  80. ( * (( * ) * )) =
  81. (( * ) * ( * )) =
  82. (( * ) * ( * )) =
  83. (( * ) * ( * )) =
  84. (( * ) * ( * )) =
  85. (( * ) * ( * )) =
  86. (( * ) * ( * )) =
  87. (( * ) * ( * )) =
  88. (( * ) * ( * )) =
  89. (( * ) * ( * )) =
  90. (( * ) * ( * )) =
  91. (( * ) * ( * )) =
  92. (( * ) * ( * )) =
  93. (( * ) * ( * )) =
  94. (( * ) * ( * )) =
  95. (( * ) * ( * )) =
  96. (( * ) * ( * )) =
  97. (( * ) * ( * )) =
  98. (( * ) * ( * )) =
  99. (( * ) * ( * )) =
  100. (( * ) * ( * )) =
  101. (( * ) * ( * )) =
  102. (( * ) * ( * )) =
  103. (( * ) * ( * )) =
  104. (( * ) * ( * )) =
  105. (( * ( * )) * ) =
  106. (( * ( * )) * ) =
  107. (( * ( * )) * ) =
  108. (( * ( * )) * ) =
  109. (( * ( * )) * ) =
  110. (( * ( * )) * ) =
  111. (( * ( * )) * ) =
  112. (( * ( * )) * ) =
  113. (( * ( * )) * ) =
  114. (( * ( * )) * ) =
  115. (( * ( * )) * ) =
  116. (( * ( * )) * ) =
  117. (( * ( * )) * ) =
  118. (( * ( * )) * ) =
  119. (( * ( * )) * ) =
  120. (( * ( * )) * ) =
  121. (( * ( * )) * ) =
  122. (( * ( * )) * ) =
  123. (( * ( * )) * ) =
  124. (( * ( * )) * ) =
  125. (( * ( * )) * ) =
  126. (( * ( * )) * ) =
  127. (( * ( * )) * ) =
  128. (( * ( * )) * ) =
  129. ((( * ) * ) * ) =
  130. ((( * ) * ) * ) =
  131. ((( * ) * ) * ) =
  132. ((( * ) * ) * ) =
  133. ((( * ) * ) * ) =
  134. ((( * ) * ) * ) =
  135. ((( * ) * ) * ) =
  136. ((( * ) * ) * ) =
  137. ((( * ) * ) * ) =
  138. ((( * ) * ) * ) =
  139. ((( * ) * ) * ) =
  140. ((( * ) * ) * ) =
  141. ((( * ) * ) * ) =
  142. ((( * ) * ) * ) =
  143. ((( * ) * ) * ) =
  144. ((( * ) * ) * ) =
  145. ((( * ) * ) * ) =
  146. ((( * ) * ) * ) =
  147. ((( * ) * ) * ) =
  148. ((( * ) * ) * ) =
  149. ((( * ) * ) * ) =
  150. ((( * ) * ) * ) =
  151. ((( * ) * ) * ) =
  152. ((( * ) * ) * ) =
  153. (( * ( * )) / ) =
  154. (( * ( * )) / ) =
  155. (( * ( * )) / ) =
  156. (( * ( * )) / ) =
  157. (( * ( * )) / ) =
  158. (( * ( * )) / ) =
  159. ((( * ) * ) / ) =
  160. ((( * ) * ) / ) =
  161. ((( * ) * ) / ) =
  162. ((( * ) * ) / ) =
  163. ((( * ) * ) / ) =
  164. ((( * ) * ) / ) =
  165. ( * (( * ) / )) =
  166. ( * (( * ) / )) =
  167. ( * (( * ) / )) =
  168. ( * (( * ) / )) =
  169. ( * (( * ) / )) =
  170. ( * (( * ) / )) =
  171. (( * ) * ( / )) =
  172. (( * ) * ( / )) =
  173. (( * ) * ( / )) =
  174. (( * ) * ( / )) =
  175. (( * ) * ( / )) =
  176. (( * ) * ( / )) =
  177. ((( * ) / ) * ) =
  178. ((( * ) / ) * ) =
  179. ((( * ) / ) * ) =
  180. ((( * ) / ) * ) =
  181. ((( * ) / ) * ) =
  182. ((( * ) / ) * ) =
  183. ( / ( / ( * ))) =
  184. ( / ( / ( * ))) =
  185. ( / ( / ( * ))) =
  186. ( / ( / ( * ))) =
  187. ( / ( / ( * ))) =
  188. ( / ( / ( * ))) =
  189. (( * ) / ( / )) =
  190. (( * ) / ( / )) =
  191. (( * ) / ( / )) =
  192. (( * ) / ( / )) =
  193. (( * ) / ( / )) =
  194. (( * ) / ( / )) =
  195. ( * ( * ( / ))) =
  196. ( * ( * ( / ))) =
  197. ( * ( * ( / ))) =
  198. ( * ( * ( / ))) =
  199. ( * ( * ( / ))) =
  200. ( * ( * ( / ))) =
  201. ( * (( / ) * )) =
  202. ( * (( / ) * )) =
  203. ( * (( / ) * )) =
  204. ( * (( / ) * )) =
  205. ( * (( / ) * )) =
  206. ( * (( / ) * )) =
  207. (( / ) * ( * )) =
  208. (( / ) * ( * )) =
  209. (( / ) * ( * )) =
  210. (( / ) * ( * )) =
  211. (( / ) * ( * )) =
  212. (( / ) * ( * )) =
  213. (( * ( / )) * ) =
  214. (( * ( / )) * ) =
  215. (( * ( / )) * ) =
  216. (( * ( / )) * ) =
  217. (( * ( / )) * ) =
  218. (( * ( / )) * ) =
  219. ((( / ) * ) * ) =
  220. ((( / ) * ) * ) =
  221. ((( / ) * ) * ) =
  222. ((( / ) * ) * ) =
  223. ((( / ) * ) * ) =
  224. ((( / ) * ) * ) =
  225. ( * ( / ( / ))) =
  226. ( * ( / ( / ))) =
  227. ( * ( / ( / ))) =
  228. ( * ( / ( / ))) =
  229. ( * ( / ( / ))) =
  230. ( * ( / ( / ))) =
  231. (( / ( / )) * ) =
  232. (( / ( / )) * ) =
  233. (( / ( / )) * ) =
  234. (( / ( / )) * ) =
  235. (( / ( / )) * ) =
  236. (( / ( / )) * ) =
  237. ( / (( / ) / )) =
  238. ( / (( / ) / )) =
  239. ( / (( / ) / )) =
  240. ( / (( / ) / )) =
  241. ( / (( / ) / )) =
  242. ( / (( / ) / )) =

对于一些平时口算相对稍难的一些组合也是毫无压力,例如{1, 5, 5, 5}, {3, 3, 7, 7}, {3, 3, 8, 8},有兴趣的看官口算试试 :)

用C#表达式树优雅的计算24点的更多相关文章

  1. C#学习笔记(九):LINQ和表达式树

    LINQ LINQ:语言集成查询(Language Integrated Query)是一组用于c#和Visual Basic语言的扩展.它允许编写C#或者Visual Basic代码以查询数据库相同 ...

  2. 程序猿修仙之路--数据结构之你是否真的懂数组? c#socket TCP同步网络通信 用lambda表达式树替代反射 ASP.NET MVC如何做一个简单的非法登录拦截

    程序猿修仙之路--数据结构之你是否真的懂数组?   数据结构 但凡IT江湖侠士,算法与数据结构为必修之课.早有前辈已经明确指出:程序=算法+数据结构  .要想在之后的江湖历练中通关,数据结构必不可少. ...

  3. C#3.0新特性:隐式类型、扩展方法、自动实现属性,对象/集合初始值设定、匿名类型、Lambda,Linq,表达式树、可选参数与命名参数

    一.隐式类型var 从 Visual C# 3.0 开始,在方法范围中声明的变量可以具有隐式类型var.隐式类型可以替代任何类型,编译器自动推断类型. 1.var类型的局部变量必须赋予初始值,包括匿名 ...

  4. c# 表达式树(一)

    前言 打算整理c# 代码简化史系列,所以相关的整理一下,简单的引出一下概念. 什么是表达式树呢? 表达式树以树形数据结构表示代码,其中每一个节点都是一种表达式,比如方法调用和 x < y 这样的 ...

  5. C# 委托、事件、表达式树理解

    1.什么是委托? 委托是一种动态调用方法的类型,属于引用型. 委托是对方法的抽象和封装.委托对象实质上代表了方法的引用(即内存地址) 所有的异步都是委托   委托就是函数当入参   委托被各种语法糖遮 ...

  6. C# Lambda表达式详解,及Lambda表达式树的创建

    最近由于项目需要,刚刚学完了Action委托和Func<T>委托,发现学完了委托就必须学习lambda表达式,委托和Lambda表达式联合起来,才能充分的体现委托的便利.才能使代码更加简介 ...

  7. C#中的Lambda表达式和表达式树

    在C# 2.0中,通过方法组转换和匿名方法,使委托的实现得到了极大的简化.但是,匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性可能就会受到影响.C# 3.0中出现的Lambda表达式在 ...

  8. LinQ实战学习笔记(三) 序列,查询操作符,查询表达式,表达式树

    序列 延迟查询执行 查询操作符 查询表达式 表达式树 (一) 序列 先上一段代码, 这段代码使用扩展方法实现下面的要求: 取进程列表,进行过滤(取大于10M的进程) 列表进行排序(按内存占用) 只保留 ...

  9. C#在泛型类中,通过表达式树构造lambda表达式

    场景 最近对爬虫的数据库架构做调整,需要将数据迁移到MongoDB上去,需要重新实现一个针对MongoDB的Dao泛型类,好吧,动手开工,当实现删除操作的时候问题来了. 我们的删除操作定义如下:voi ...

随机推荐

  1. 浏览器js console对象

    js中调用console写日志 console.log("some log"); console.warn("some warning"); console.e ...

  2. nop 添加字段

    一.Libraries 1.core 层------------实体字段 2.data-Map----------映射到数据库 二.Admin 1.Models  --------admin界面模型  ...

  3. decode 横竖转换 2

    select sno,nvl(to_char(sum(decode(cno,'c001',score))),'-') c001,nvl(to_char(sum(decode(cno,'c002',sc ...

  4. 关于collapsed margin(外边距合并)

    这是前面写postion定位时写到最后面的例子的时候发现的一个问题,于是专门写一篇随笔来解释记录一下,毕竟两个知识点同时写在一篇文章里面有点混乱的感觉.. 上篇随笔position定位遇到的问题在这里 ...

  5. 封装getElementsByClassName()

    function getElementsByClassName(node,classname){             if(node.getElementsByClassName){        ...

  6. C++混合编程之idlcpp教程Lua篇(4)

    上一篇在这  C++混合编程之idlcpp教程Lua篇(3) 与前面的工程相似,工程LuaTutorial2中,同样加入了三个文件 LuaTutorial2.cpp, Tutorial2.i, tut ...

  7. 配置本地IIS和VS自带IIS

    以前调试网站一直用的vs自带的IIS,做为学习没啥大碍,但要是用于团队项目开发就会带来诸多不便.团队开发项目有统一的网站端口号.文件目录什么的,端口号可以在配置文件中修改倒也没啥,但是要在自己的项目中 ...

  8. qooxdoo 3.0 发布,JavaScript 的 GUI 框架

    qooxdoo 3.0 是一个主要的版本,包含很多新特性和内部的改动,qooxdoo 3.0 是一个通用的 JS 框架,主要改进体现在 qx.Desktop, qx.Mobile, 和 qx.Webs ...

  9. Linux下oracle11gR2系统安装到数据库建立配置及最后oracle的dmp文件导入一站式操作记录

    简介 之前也在linux下安装过oralce,可每次都是迷迷糊糊的,因为大脑一片空白,网上随便看见一个文档就直接复制,最后搞了乱七八糟,虽然装上了,却乱得很,现在记录下来,希望能给其他网上朋友遇到问题 ...

  10. WebApi与手机客户端通信安全机制

    最近公司有几个项目需要开发手机客户端,服务器端选用WebApi,那么如何保证手机客户端在请求服务器端时数据不被篡改,如何保证一个http请求的失效机制,下面总结一下我们在项目中针对这两个问题的解决方案 ...