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; } }}