C# 版本的24点实现

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...

转载于:https://www.cnblogs.com/thomas888/p/csharp-calc24.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值