C# 版本的24点实现。

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

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

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

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

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace calc24
{
class MainClass
{
public static void Main (string[] args)
{
var permuteOfNums = Permute (new List<int> { 4, 5, 6, 7 }); foreach (var op1 in new List<string>{"+","-","*","/"}) {
foreach (var op2 in new List<string>{"+","-","*","/"}) {
foreach (var op3 in new List<string>{"+","-","*","/"}) {
var ops = new List<string>{ op1, op2, op3 }; foreach (var node in AllCompleteBinaryTreesOf7Nodes()) {
foreach (var nums in permuteOfNums) {
var tree = CreateOne24CalculationFormula (node, nums, ops);
try {
var result = Evaluate (tree); if (Math.Abs (result - 24) < 0.0001) {
Console.WriteLine (BinaryTreeString (tree));
}
} catch (DivideByZeroException) { }
}
}
}
}
}
} static float Evaluate (Node node)
{
switch (node.Data) {
case "+":
return Evaluate (node.Left) + Evaluate (node.Right);
case "-":
return Evaluate (node.Left) - Evaluate (node.Right);
case "*":
return Evaluate (node.Left) * Evaluate (node.Right);
case "/":
return Evaluate (node.Left) / Evaluate (node.Right);
default:
return float.Parse (node.Data);
}
} static Node CreateOne24CalculationFormula (Node node, List<int> nums, List<string> operators)
{ Node result = null;
var iNums = 0;
var iOps = 0; Func<Node, Node> copy = null; copy = (src) => {
Node dest; if (src.Left == null && src.Right == null) {
dest = new Node (null, null, nums [iNums++].ToString ());
} else {
var left = copy (src.Left);
var right = copy (src.Right); dest = new Node (left, right, operators [iOps++]);
} return dest;
}; result = copy (node); return result;
} static IEnumerable<List<T>> Permute<T> (List<T> elements)
{
if (elements.Count == 1)
return EnumerableOfOneElement (elements); IEnumerable<List<T>> result = null; foreach (var first in elements) {
var remaining = elements.ToArray ().ToList ();
remaining.Remove (first); var permutesOfRemaining = Permute (remaining); foreach (var p in permutesOfRemaining) {
var arr = new List<T> { first };
arr.AddRange (p); var seq = EnumerableOfOneElement (arr); if (result == null) {
result = seq;
} else {
result = Enumerable.Union (result, seq);
}
}
} return result;
} static IEnumerable<T> EnumerableOfOneElement<T> (T element)
{
yield return element;
} static IEnumerable<Node> AllCompleteBinaryTreesOf7Nodes ()
{
var trees = AllBinaryTrees (7);
return (from t in trees
where IsCompleteBinaryTree (t)
select t);
} static bool IsCompleteBinaryTree (Node node)
{
if (node == null)
return true; if (node.Left == null && node.Right != null ||
node.Left != null && node.Right == null)
return false; return IsCompleteBinaryTree (node.Left) && IsCompleteBinaryTree (node.Right);
} static IEnumerable<Node> AllBinaryTrees (int size)
{
if (size == 0)
return new Node[] { null };
return from i in Enumerable.Range (0, size)
from left in AllBinaryTrees (i)
from right in AllBinaryTrees (size - 1 - i)
select new Node (left, right, "");
} public static string BinaryTreeString (Node node)
{
var sb = new StringBuilder ();
Action<Node> f = null;
f = n => {
if (n == null) {
//sb.Append ("x");
} else if (new []{ "+", "-", "*", "/" }.Contains (n.Data)) { sb.Append ("(");
f (n.Left); sb.Append (" " + n.Data + " "); f (n.Right);
sb.Append (")"); } else {
sb.Append (n.Data);
}
};
f (node);
return sb.ToString ();
}
} class Node
{
public Node Left { get; set; } public Node Right { get; set; } public string Data { get; set; } public Node ()
{ } public Node (Node left, Node right, string data)
{
this.Left = left;
this.Right = right;
this.Data = data;
}
}
}

测试:

(4 * ((5 + 7) - 6))
(4 * ((7 + 5) - 6))
((5 + 7) * (6 - 4))
((7 + 5) * (6 - 4))
(((5 + 7) - 6) * 4)
(((7 + 5) - 6) * 4)
(4 * (5 + (7 - 6)))
(4 * (7 + (5 - 6)))
(4 * ((5 - 6) + 7))
(4 * ((7 - 6) + 5))
((6 - 4) * (5 + 7))
((6 - 4) * (7 + 5))
((5 + (7 - 6)) * 4)
((7 + (5 - 6)) * 4)
(((5 - 6) + 7) * 4)
(((7 - 6) + 5) * 4)
(4 * (5 - (6 - 7)))
(4 * (7 - (6 - 5)))
((5 - (6 - 7)) * 4)
((7 - (6 - 5)) * 4) 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. BZOJ1821 [JSOI2010]Group 部落划分 Group Kruskal

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1821 题意概括 平面上有n个点,现在把他们划分成k个部分,求不同部分之间最近距离的最大值. 两个部 ...

  2. 【noip模拟赛5】任务分配 降维dp

    描述 现有n个任务,要交给A和B完成.每个任务给A或给B完成,所需的时间分别为ai和bi.问他们完成所有的任务至少要多少时间. 输入 第一行一个正整数n,表示有n个任务.接下来有n行,每行两个正整数a ...

  3. UVA - 11149 (矩阵快速幂+倍增法)

    第一道矩阵快速幂的题:模板题: #include<stack> #include<queue> #include<cmath> #include<cstdio ...

  4. C++语言实现-拓扑排序

    1.拓扑排序的概念 对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则 ...

  5. python tkinter-按钮.标签.文本框、输入框

    按钮 无功能按钮 Button的text属性显示按钮上的文本 tkinter.Button(form, text='hello button').pack() 无论怎么变幻窗体大小,永远都在窗体的最上 ...

  6. poj 1160 Post Office 【区间dp】

    <题目链接> 转载于:>>> 题目大意: 一条高速公路,有N个村庄,每个村庄均有一个唯一的坐标,选择P个村庄建邮局,问怎么选择,才能使每个村庄到其最近邮局的距离和最小?最 ...

  7. DB2<RedHed Linux> 创建数据库

    1 DB2 安装后组情况 Users User Desc Username Home folder Password Group   Administration User -dasusr1 /hom ...

  8. 洛谷.3437.[POI2006]TET-Tetris 3D(二维线段树)

    题目链接 下落一个d*s的方块,则要在这个平面区域找一个最高的h' 更新整个平面区域的值为h+h' 对于本题,维护最大高度h和all 对于平面的x轴维护一棵线段树t1,每个t1的节点维护对应y轴的两棵 ...

  9. 浅表拷贝vs深度拷贝

    浅表复制,只是创建所有的值类型,所有的引用类型还是会指向被复制的对象的引用. 故,当被复制的对象的引用类型发生改变的同事,复制的对象相应的 引用类型的值也是会发生改变的. 所以事件字段也是一个引用类型 ...

  10. 2016年3月12日Android学习笔记

    1. //此句不能忘,否则onFling左右滑动不起作用 mLlExamView.setLongClickable(true); mLlExamView.setOnTouchListener(new ...