C# 版本的24点实现。

已经实现基本功能,可以正确的算 3, 3, 8, 8 这类组合。

稍加修改就可以支持任意数目的操作数和操作符组合形成的四则运算表达式,不限于24点。

代码还比较简单粗糙,晚一点优化了再更新此贴。

关于二叉树拓扑结构的遍历,参考了:

http://blogs.msdn.com/b/ericlippert/archive/2010/04/19/every-binary-tree-there-is.aspx

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace calc24
  6. {
  7. class MainClass
  8. {
  9. public static void Main (string[] args)
  10. {
  11. var permuteOfNums = Permute (new List<int> { 4, 5, 6, 7 });
  12. foreach (var op1 in new List<string>{"+","-","*","/"}) {
  13. foreach (var op2 in new List<string>{"+","-","*","/"}) {
  14. foreach (var op3 in new List<string>{"+","-","*","/"}) {
  15. var ops = new List<string>{ op1, op2, op3 };
  16. foreach (var node in AllCompleteBinaryTreesOf7Nodes()) {
  17. foreach (var nums in permuteOfNums) {
  18. var tree = CreateOne24CalculationFormula (node, nums, ops);
  19. try {
  20. var result = Evaluate (tree);
  21. if (Math.Abs (result - 24) < 0.0001) {
  22. Console.WriteLine (BinaryTreeString (tree));
  23. }
  24. } catch (DivideByZeroException) {
  25. }
  26. }
  27. }
  28. }
  29. }
  30. }
  31. }
  32. static float Evaluate (Node node)
  33. {
  34. switch (node.Data) {
  35. case "+":
  36. return Evaluate (node.Left) + Evaluate (node.Right);
  37. case "-":
  38. return Evaluate (node.Left) - Evaluate (node.Right);
  39. case "*":
  40. return Evaluate (node.Left) * Evaluate (node.Right);
  41. case "/":
  42. return Evaluate (node.Left) / Evaluate (node.Right);
  43. default:
  44. return float.Parse (node.Data);
  45. }
  46. }
  47. static Node CreateOne24CalculationFormula (Node node, List<int> nums, List<string> operators)
  48. {
  49. Node result = null;
  50. var iNums = 0;
  51. var iOps = 0;
  52. Func<Node, Node> copy = null;
  53. copy = (src) => {
  54. Node dest;
  55. if (src.Left == null && src.Right == null) {
  56. dest = new Node (null, null, nums [iNums++].ToString ());
  57. } else {
  58. var left = copy (src.Left);
  59. var right = copy (src.Right);
  60. dest = new Node (left, right, operators [iOps++]);
  61. }
  62. return dest;
  63. };
  64. result = copy (node);
  65. return result;
  66. }
  67. static IEnumerable<List<T>> Permute<T> (List<T> elements)
  68. {
  69. if (elements.Count == 1)
  70. return EnumerableOfOneElement (elements);
  71. IEnumerable<List<T>> result = null;
  72. foreach (var first in elements) {
  73. var remaining = elements.ToArray ().ToList ();
  74. remaining.Remove (first);
  75. var permutesOfRemaining = Permute (remaining);
  76. foreach (var p in permutesOfRemaining) {
  77. var arr = new List<T> { first };
  78. arr.AddRange (p);
  79. var seq = EnumerableOfOneElement (arr);
  80. if (result == null) {
  81. result = seq;
  82. } else {
  83. result = Enumerable.Union (result, seq);
  84. }
  85. }
  86. }
  87. return result;
  88. }
  89. static IEnumerable<T> EnumerableOfOneElement<T> (T element)
  90. {
  91. yield return element;
  92. }
  93. static IEnumerable<Node> AllCompleteBinaryTreesOf7Nodes ()
  94. {
  95. var trees = AllBinaryTrees (7);
  96. return (from t in trees
  97. where IsCompleteBinaryTree (t)
  98. select t);
  99. }
  100. static bool IsCompleteBinaryTree (Node node)
  101. {
  102. if (node == null)
  103. return true;
  104. if (node.Left == null && node.Right != null ||
  105. node.Left != null && node.Right == null)
  106. return false;
  107. return IsCompleteBinaryTree (node.Left) && IsCompleteBinaryTree (node.Right);
  108. }
  109. static IEnumerable<Node> AllBinaryTrees (int size)
  110. {
  111. if (size == 0)
  112. return new Node[] { null };
  113. return from i in Enumerable.Range (0, size)
  114. from left in AllBinaryTrees (i)
  115. from right in AllBinaryTrees (size - 1 - i)
  116. select new Node (left, right, "");
  117. }
  118. public static string BinaryTreeString (Node node)
  119. {
  120. var sb = new StringBuilder ();
  121. Action<Node> f = null;
  122. f = n => {
  123. if (n == null) {
  124. //sb.Append ("x");
  125. } else if (new []{ "+", "-", "*", "/" }.Contains (n.Data)) {
  126. sb.Append ("(");
  127. f (n.Left);
  128. sb.Append (" " + n.Data + " ");
  129. f (n.Right);
  130. sb.Append (")");
  131. } else {
  132. sb.Append (n.Data);
  133. }
  134. };
  135. f (node);
  136. return sb.ToString ();
  137. }
  138. }
  139. class Node
  140. {
  141. public Node Left { get; set; }
  142. public Node Right { get; set; }
  143. public string Data { get; set; }
  144. public Node ()
  145. {
  146. }
  147. public Node (Node left, Node right, string data)
  148. {
  149. this.Left = left;
  150. this.Right = right;
  151. this.Data = data;
  152. }
  153. }
  154. }

测试:

  1. (4 * ((5 + 7) - 6))
  2. (4 * ((7 + 5) - 6))
  3. ((5 + 7) * (6 - 4))
  4. ((7 + 5) * (6 - 4))
  5. (((5 + 7) - 6) * 4)
  6. (((7 + 5) - 6) * 4)
  7. (4 * (5 + (7 - 6)))
  8. (4 * (7 + (5 - 6)))
  9. (4 * ((5 - 6) + 7))
  10. (4 * ((7 - 6) + 5))
  11. ((6 - 4) * (5 + 7))
  12. ((6 - 4) * (7 + 5))
  13. ((5 + (7 - 6)) * 4)
  14. ((7 + (5 - 6)) * 4)
  15. (((5 - 6) + 7) * 4)
  16. (((7 - 6) + 5) * 4)
  17. (4 * (5 - (6 - 7)))
  18. (4 * (7 - (6 - 5)))
  19. ((5 - (6 - 7)) * 4)
  20. ((7 - (6 - 5)) * 4)
  21. Press any key to continue...

C# 版本的24点实现的更多相关文章

  1. Racket 版本的 24 点实现

    Racket 版本的 24 点实现 #lang racket ; Author: woodfox ; Date: Oct 11, 2014 ; ==================== 1. Non- ...

  2. 团队作业4--第一次项目冲刺(Alpha版本)预备工作

    小组说明 我们组是从周一开始对项目进行研究讨论并编程的,因为我们看截止日期是周日,就从周一才开始,起步晚了,是我们认识上的失误,导致我们周一周二的步伐没有协调好,项目进展的不稳定,但是我们在上周末并不 ...

  3. ESP-IDF版本2.1.1

    版本2.1.1是一个错误修复版本.它包括对KRACK和BlueBorne漏洞的修复. 版本2.1.1的文档可在http://esp-idf.readthedocs.io/en/v2.1.1/上找到. ...

  4. Android 7.0以上版本 系统解决拍照的问题 exposed beyond app through ClipData.Item.getUri()

    解决方案1: android.os.FileUriExposedException: file:///storage/emulated/0/ilive/images/photophoto.jpeg e ...

  5. 交叉编译OpenCV的Android版本

    交叉编译OpenCV的Android版本 OpenCV作为一个强大的图像处理库,在Android上也有强大的应用. OpenCV官网提供了SDK的下载,可以直接下载使用 OpenCV官网地址:http ...

  6. selenium:chromedriver与chrome版本的对应关系

    转自:http://blog.csdn.NET/huilan_same/article/details/51896672 再使用selenium打开chrome浏览器的时候,需要用chromedriv ...

  7. 四、10分钟ToPandas_0.24.2

    # Author:Zhang Yuan整理,版本Pandas0.24.2 # 0. 习惯上,我们会按下面格式引入所需要的包: import pandas as pd import numpy as n ...

  8. OpenCV.3.4.6_VS2015&cmake编译x86版本的bin&lib

    ZC:<<OpenCV3编程入门>> 的 2.2.2 中也有该内容的讲解 1.参考网址:opencv3.3.0+vs2015+cmake编译opencv x86 - wowo的 ...

  9. PDF 文件编写器 C# 类库(版本 1.28.0)使用详解

    PDF File Writer 是一个 C# .NET 类库,允许应用程序创建 PDF 文件. PDF File Writer C# 类库使 .NET 应用程序能够生成 PDF 文档.该库使应用程序免 ...

随机推荐

  1. Python subprocess方法

    import subprocess #subprocess.call("df -h",shell=True,stdout=subprocess.PIPE)#打印到视图,但是不能保存 ...

  2. 8.Django-form组件

    1.form组件的校验功能 文件formsdemo models from django.db import models # Create your models here. class UserI ...

  3. Digital biquad filter

    Direct Form 1 The most straightforward implementation is the Direct Form 1, which has the following ...

  4. hdu 1002 A + B Problem II【大数加法】

    题目链接>>>>>> 题目大意:手动模拟大数加法,从而进行两个大数的加法运算 #include <stdio.h> #include <strin ...

  5. HTTP协议学习笔记(一)

    HTTP协议学习笔记(一) 1.HTTP协议用于客户端和服务端之间的通信 客户端:请求访问文本或图像等资源的一端服务端:提供资源响应的一端 在两台计算机之间使用HTTP协议通信时,在一条通信线路上必定 ...

  6. python3之Django表单(一)

    1.HTML中的表单 在HTML种,表单是在<form>...</form>种的元素,它允许用户输入文本,选择选项,操作对象等,然后发送这些数据到服务器 表单元素允许用户在表单 ...

  7. C#多线程编程实战(二):线程同步

    2.1 简介 竞争条件:多个线程同时使用共享对象.需要同步这些线程使得共享对象的操作能够以正确的顺序执行 线程同步问题:多线程的执行并没有正确的同步,当一个线程执行递增和递减操作时,其他线程需要依次等 ...

  8. C# DataGridView插入DB

    public static bool ContrastColumns(DataColumnCollection co1, DataGridViewColumnCollection co2) { boo ...

  9. Java 之递归删除目录

    Java 之递归删除目录 一.思想 必须从最里层的文件开始删除,使用递归删除. 二.源代码:RecursiveDeleteDirectory.java package cn.com.zfc.day01 ...

  10. LOJ.6062.[2017山东一轮集训]Pair(Hall定理 线段树)

    题目链接 首先Bi之间的大小关系没用,先对它排序,假设从小到大排 那么每个Ai所能匹配的Bi就是一个B[]的后缀 把一个B[]后缀的匹配看做一条边的覆盖,设Xi为Bi被覆盖的次数 容易想到 对于每个i ...