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