24点算法源码(C#)

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace HeroAssociation
{
    /// <summary>
    /// 24 点
    /// </summary>
    public class TwentyFourPoint
    {
        /// <summary>
        /// 分数类,用于分数运算。
        /// </summary>
        class Fraction
        {
            /// <summary>
            /// 分子
            /// </summary>
            private int numerator;
            /// <summary>
            /// 分母
            /// </summary>
            private int denominator;

            public Fraction(int number)
                : this(number, 1)
            { }

            public Fraction(int numerator, int denominator)
            {
                if (denominator == 0)
                {
                    throw new DivideByZeroException("分母不能为0");
                }
                int sign = numerator * denominator < 0 ? -1 : 1;
                numerator = Abs(numerator);
                denominator = Abs(denominator);
                this.numerator = sign * numerator / Gcd(numerator, denominator);
                this.denominator = denominator / Gcd(numerator, denominator);
            }

            public static Fraction operator +(Fraction a, Fraction b)
            {
                if (a.denominator == b.denominator)
                {
                    return new Fraction(a.numerator + b.numerator, a.denominator);
                }
                else
                {
                    return new Fraction(a.numerator * b.denominator + b.numerator * a.denominator, a.denominator * b.denominator);
                }
            }

            public static Fraction operator -(Fraction a, Fraction b)
            {
                if (a.denominator == b.denominator)
                {
                    return new Fraction(a.numerator - b.numerator, a.denominator);
                }
                else
                {
                    return new Fraction(a.numerator * b.denominator - b.numerator * a.denominator, a.denominator * b.denominator);
                }
            }

            public static Fraction operator *(Fraction a, Fraction b)
            {
                return new Fraction(a.numerator * b.numerator, a.denominator * b.denominator);
            }

            public static Fraction operator /(Fraction a, Fraction b)
            {
                return new Fraction(a.numerator * b.denominator, a.denominator * b.numerator);
            }

            public override bool Equals(object obj)
            {
                Fraction a = (Fraction)obj;
                return this.numerator == a.numerator && this.denominator == a.denominator;
            }

            public override int GetHashCode()
            {
                return this.numerator.GetHashCode() ^ this.denominator.GetHashCode();
            }

            /// <summary>
            /// 是否是整数
            /// </summary>
            /// <returns></returns>
            public bool IsInteger()
            {
                return numerator % denominator == 0;
            }

            /// <summary>
            /// 最大公约数
            /// </summary>
            /// <param name="a"></param>
            /// <param name="b"></param>
            /// <returns></returns>
            private static int Gcd(int a, int b)
            {
                return b == 0 ? a : Gcd(b, a % b);
            }

            private static int Abs(int a)
            {
                return a < 0 ? -a : a;
            }

            public int Result()
            {
                return numerator / denominator;
            }

            public bool IsZero()
            {
                return numerator == 0;
            }
        }

        /// <summary>
        /// 算术运算组合枚举器,不改变各分数的排列顺序
        /// </summary>
        class ArithmeticIterator : IEnumerable<Fraction>
        {
            private Fraction[] fractions;

            /// <summary>
            /// 构造算术枚举对象
            /// </summary>
            /// <param name="fractions">分数数组</param>
            public ArithmeticIterator(Fraction[] fractions)
            {
                this.fractions = fractions;
            }

            public IEnumerator<Fraction> GetEnumerator()
            {
                if (fractions.Length == 1)
                {
                    yield return fractions[0];
                    yield break;
                }
                for (int i = 1; i < fractions.Length; i++)
                {
                    Fraction[] leftFractions = new Fraction[i];
                    Fraction[] rightFractions = new Fraction[fractions.Length - i];
                    Array.Copy(fractions, 0, leftFractions, 0, leftFractions.Length);
                    Array.Copy(fractions, i, rightFractions, 0, rightFractions.Length);
                    foreach (Fraction leftFraction in new ArithmeticIterator(leftFractions))
                    {
                        foreach (Fraction rightFraction in new ArithmeticIterator(rightFractions))
                        {
                            yield return leftFraction + rightFraction;
                            yield return leftFraction - rightFraction;
                            yield return leftFraction * rightFraction;
                            if (!rightFraction.IsZero())
                            {
                                yield return leftFraction / rightFraction;
                            }
                        }
                    }
                }
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }


        /// <summary>
        /// 分数全排列迭代器
        /// </summary>
        class FractionsPermutationIterator : IEnumerable<Fraction[]>
        {
            private Fraction[] fractions;
            /// <summary>
            /// 构造分数全排列迭代器
            /// </summary>
            /// <param name="fractions">分数数组</param>
            public FractionsPermutationIterator(Fraction[] fractions)
            {
                this.fractions = fractions;
            }

            public IEnumerator<Fraction[]> GetEnumerator()
            {
                if (fractions.Length == 1)
                {
                    yield return fractions;
                    yield break;
                }
                for (int idx = 0; idx < fractions.Length; idx++)
                {
                    Fraction[] result = new Fraction[fractions.Length];
                    result[0] = fractions[idx];

                    Fraction[] subFractions = RemoveAt(fractions, idx);

                    foreach (Fraction[] frs in new FractionsPermutationIterator(subFractions))
                    {
                        Array.Copy(frs, 0, result, 1, frs.Length);
                        yield return result;
                    }
                }
            }

            /// <summary>
            /// 删除素组指定位置的元素,返回新的数组。
            /// </summary>
            /// <param name="array">原数组。不改变原数组</param>
            /// <param name="idx"></param>
            /// <returns></returns>
            private static Fraction[] RemoveAt(Fraction[] array, int idx)
            {
                Fraction[] subFractions = new Fraction[array.Length - 1];

                if (idx > 0)
                {
                    //前部分
                    Array.Copy(array, 0, subFractions, 0, idx);
                }

                if (idx < array.Length - 1)
                {
                    //后半部分
                    Array.Copy(array, idx + 1, subFractions, idx, subFractions.Length - idx);
                }
                return subFractions;
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
        }


        private int a, b, c, d;

        public static bool Can24(int a, int b, int c, int d)
        {
            return new TwentyFourPoint(a, b, c, d).Can24();
        }

        public TwentyFourPoint(int a, int b, int c, int d)
        {
            this.a = a;
            this.b = b;
            this.c = c;
            this.d = d;
        }

        public bool Can24()
        {
            Fraction[] fractions = new Fraction[4];
            fractions[0] = new Fraction(this.a);
            fractions[1] = new Fraction(this.b);
            fractions[2] = new Fraction(this.c);
            fractions[3] = new Fraction(this.d);

            foreach (Fraction[] oneFractions in new FractionsPermutationIterator(fractions))
            {
                foreach (Fraction fra in new ArithmeticIterator(oneFractions))
                {
                    if (fra.IsInteger() && fra.Result() == 24)
                    {
                        return true;
                    }
                }
            }
            return false;
        }
    }
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值