/// <summary>
        /// 遞等式計算通用處理
        /// </summary>
        /// <param name="type">題型</param>
        /// <param name="expressFormat">計算表達式</param>
        /// <param name="getArguments">參數處理邏輯</param>
        /// <param name="formulas">計算式作成</param>
        private void CleverStartegy(TopicType type, string expressFormat, Func <int[]> getArguments, IList <RecursionEquationFormula> formulas)
        {
            // 當前反推判定次數(一次推算內次數累加)
            int defeated = 0;

            RecursionEquationFormula RecursionEquation = new RecursionEquationFormula
            {
                Type           = type,
                ConfixFormulas = new List <Formula>(),
                Answer         = new List <int>()
            };

            while (1 == 1)
            {
                // 如果大於三次則認為此題無法作成繼續下一題
                if (defeated == INVERSE_NUMBER)
                {
                    RecursionEquation = null;
                    break;
                }

                int[] factors = getArguments();
                if (factors == null)
                {
                    defeated++;
                    continue;
                }

                StringBuilder express = new StringBuilder();
                var           answer  = factors[3];
                express.AppendFormat(CultureInfo.CurrentCulture, expressFormat, factors[0], factors[1], factors[2]);

                // 計算式推導
                var calc = new ExpressArithmeticUtil();
                if (!calc.IsResult(express.ToString(), out int result))
                {
                    defeated++;
                    continue;
                }
                if (result != answer)
                {
                    defeated++;
                    continue;
                }
                // 加入推導出計算式集合
                calc.Formulas.ToList().ForEach(f => RecursionEquation.ConfixFormulas.Add(f));
                RecursionEquation.Answer.Add(answer);
                defeated = 0;

                break;
            }

            if (RecursionEquation != null)
            {
                formulas.Add(RecursionEquation);
            }
        }
        public void SplitExpressTest03()
        {
            Express = "40+(60-1)*5";

            var calc    = new ExpressArithmeticUtil();
            var express = calc.SplitExpress(Express);
            var list    = calc.InorderToPostorder(express);

            Assert.IsTrue(calc.IsResult(list, out int result));
            Assert.AreEqual(335, result);
        }
        public void SplitExpressTest02()
        {
            Express = "(30+10)*50+60/20";

            var calc    = new ExpressArithmeticUtil();
            var express = calc.SplitExpress(Express);
            var list    = calc.InorderToPostorder(express);

            Assert.IsTrue(calc.IsResult(list, out int result));
            Assert.AreEqual(2003, result);
        }
        public void SplitExpressTest08()
        {
            Express = "100+{10+[40+(60-10/2)]}*5";

            var calc    = new ExpressArithmeticUtil();
            var express = calc.SplitExpress(Express);
            var list    = calc.InorderToPostorder(express);

            Assert.IsTrue(calc.IsResult(list, out int result));
            Assert.AreEqual(625, result);

            Assert.IsTrue(calc.IsResult(Express, out result));
            Assert.AreEqual(625, result);
        }
        public void ArithmeticTest01()
        {
            var calc = new ExpressArithmeticUtil();

            Assert.AreEqual("7", calc.Arithmetic("3", "4", "+"));
            Assert.AreEqual("1", calc.Arithmetic("4", "3", "-"));
            Assert.AreEqual("12", calc.Arithmetic("3", "4", "*"));
            Assert.AreEqual("7", calc.Arithmetic("28", "4", "/"));

            Assert.AreEqual(3, calc.Formulas[0].LeftParameter);
            Assert.AreEqual(4, calc.Formulas[0].RightParameter);
            Assert.AreEqual(SignOfOperation.Plus, calc.Formulas[0].Sign);
            Assert.AreEqual(7, calc.Formulas[0].Answer);
        }
        public void SplitExpressTest04()
        {
            var calc    = new ExpressArithmeticUtil();
            var express = calc.SplitExpress("40+5");
            var list    = calc.InorderToPostorder(express);

            Assert.IsTrue(calc.IsResult(list, out int result01));
            Assert.AreEqual(45, result01);

            Assert.IsTrue(calc.IsResult("40+5", out result01));
            Assert.AreEqual(45, result01);

            express = calc.SplitExpress("40/5");
            list    = calc.InorderToPostorder(express);
            Assert.IsTrue(calc.IsResult(list, out int result02));
            Assert.AreEqual(8, result02);

            Assert.IsTrue(calc.IsResult("40/5", out result02));
            Assert.AreEqual(8, result02);

            express = calc.SplitExpress("40*5");
            list    = calc.InorderToPostorder(express);
            Assert.IsTrue(calc.IsResult(list, out int result03));
            Assert.AreEqual(200, result03);

            Assert.IsTrue(calc.IsResult("40*5", out result03));
            Assert.AreEqual(200, result03);

            express = calc.SplitExpress("40-5");
            list    = calc.InorderToPostorder(express);
            Assert.IsTrue(calc.IsResult(list, out int result04));
            Assert.AreEqual(35, result04);

            Assert.IsTrue(calc.IsResult("40-5", out result04));
            Assert.AreEqual(35, result04);
        }
        public void SplitExpressTest01()
        {
            Express = "(3+1)*5-6/2";

            var calc    = new ExpressArithmeticUtil();
            var express = calc.SplitExpress(Express);

            Assert.AreEqual(12, express.Count);

            // 中序表達式隊列
            var resultExpress = express.ToArray();

            Assert.AreEqual("(", resultExpress[0]);
            Assert.AreEqual("3", resultExpress[1]);
            Assert.AreEqual("+", resultExpress[2]);
            Assert.AreEqual("1", resultExpress[3]);
            Assert.AreEqual(")", resultExpress[4]);
            Assert.AreEqual("*", resultExpress[5]);
            Assert.AreEqual("5", resultExpress[6]);
            Assert.AreEqual("-", resultExpress[7]);
            Assert.AreEqual("6", resultExpress[8]);
            Assert.AreEqual("/", resultExpress[9]);
            Assert.AreEqual("2", resultExpress[10]);
            Assert.AreEqual("#", resultExpress[11]);

            var list = calc.InorderToPostorder(express);

            Assert.AreEqual(9, list.Count);

            Assert.IsTrue(calc.IsResult(list, out int result));
            Assert.AreEqual(17, result);

            Assert.AreEqual(4, calc.Formulas.Count);

            var f1 = calc.Formulas[0];

            Assert.AreEqual(3, f1.LeftParameter);
            Assert.AreEqual(SignOfOperation.Plus, f1.Sign);
            Assert.AreEqual(1, f1.RightParameter);
            Assert.AreEqual(4, f1.Answer);

            var f2 = calc.Formulas[1];

            Assert.AreEqual(4, f2.LeftParameter);
            Assert.AreEqual(SignOfOperation.Multiple, f2.Sign);
            Assert.AreEqual(5, f2.RightParameter);
            Assert.AreEqual(20, f2.Answer);

            var f3 = calc.Formulas[2];

            Assert.AreEqual(6, f3.LeftParameter);
            Assert.AreEqual(SignOfOperation.Division, f3.Sign);
            Assert.AreEqual(2, f3.RightParameter);
            Assert.AreEqual(3, f3.Answer);

            var f4 = calc.Formulas[3];

            Assert.AreEqual(20, f4.LeftParameter);
            Assert.AreEqual(SignOfOperation.Subtraction, f4.Sign);
            Assert.AreEqual(3, f4.RightParameter);
            Assert.AreEqual(17, f4.Answer);
        }
        /// <summary>
        /// 綜合題型巧算(合併)
        /// </summary>
        /// <param name="formulas">計算式作成</param>
        protected virtual void CleverWithSyntheticCombine(IList <CleverCalculationFormula> formulas)
        {
            // 當前反推判定次數(一次推算內次數累加)
            int defeated = 0;

            CleverCalculationFormula cleverCalculation = new CleverCalculationFormula
            {
                Type           = (int)Synthetic.Combine,
                ConfixFormulas = new List <Formula>(),
                Answer         = new List <int>()
            };

            while (1 == 1)
            {
                // 如果大於三次則認為此題無法作成繼續下一題
                if (defeated == INVERSE_NUMBER)
                {
                    cleverCalculation = null;
                    break;
                }

                cleverCalculation.ConfixFormulas.Clear();
                cleverCalculation.Answer.Clear();

                var answer = 0;
                // 獲取一個10以內的共有因數
                int factorShare = CommonUtil.GetRandomNumber(3, 9);

                // 合併方法(加法或者减法)
                SignOfOperation combine = CommonUtil.GetRandomNumber(SignOfOperation.Plus, SignOfOperation.Subtraction);

                StringBuilder express = new StringBuilder();
                // 加法合併
                if (combine == SignOfOperation.Plus)
                {
                    int factor1 = CommonUtil.GetRandomNumber(1, 9);

                    // 加法合併的兩種情況:
                    // 1.相加之和是整十數
                    int factor2 = CommonUtil.GetRandomNumber(1, 50, condition: _ => (_ % 10 == 0 || _ + factor1 <= 10) && _ != factor1, getDefault: () => 30);
                    // 2.相加之和是十
                    if (factor2 > 10)
                    {
                        factor2 -= factor1;
                    }
                    // 隨機排列計算式各參數(打亂參數位置)
                    SetNewGuidFactors(out List <int> factors1, factorShare, factor1);
                    SetNewGuidFactors(out List <int> factors2, factorShare, factor2);
                    // eg: 8 * 5 + 2 * 5 = (8 + 2) * 5 = 10 * 5
                    express.AppendFormat(CultureInfo.CurrentCulture, "{0}*{1}+{2}*{3}", factors1[0], factors1[1], factors2[0], factors2[1]);

                    answer = (factor1 + factor2) * factorShare;
                    cleverCalculation.ConfixFormulas.Add(new Formula(factor1 + factor2, factorShare, answer, SignOfOperation.Multiple));
                    cleverCalculation.Answer.Add(answer);
                }
                // 減法合併
                else
                {
                    int factor1 = CommonUtil.GetRandomNumber(11, 19);
                    int factor2 = CommonUtil.GetRandomNumber(5, 9, condition: _ => factor1 - _ <= 10, getDefault: () => 5);

                    // 隨機排列計算式各參數(打亂參數位置)
                    SetNewGuidFactors(out List <int> factors1, factorShare, factor1);
                    SetNewGuidFactors(out List <int> factors2, factorShare, factor2);
                    // eg: 18 * 5 - 9 * 5 = (18 - 9) * 5 = 20
                    express.AppendFormat(CultureInfo.CurrentCulture, "{0}*{1}-{2}*{3}", factors1[0], factors1[1], factors2[0], factors2[1]);

                    answer = (factor1 - factor2) * factorShare;
                    cleverCalculation.ConfixFormulas.Add(new Formula(factor1 - factor2, factorShare, answer, SignOfOperation.Multiple));
                    cleverCalculation.Answer.Add(answer);
                }

                // 計算式推導
                var calc = new ExpressArithmeticUtil();
                if (!calc.IsResult(express.ToString(), out int result))
                {
                    defeated++;
                    continue;
                }
                if (result != answer)
                {
                    defeated++;
                    continue;
                }
                // 加入推導出計算式集合
                calc.Formulas.ToList().ForEach(f => cleverCalculation.ConfixFormulas.Add(f));
                defeated = 0;

                break;
            }

            if (cleverCalculation != null)
            {
                formulas.Add(cleverCalculation);
            }
        }
        /// <summary>
        /// 綜合題型巧算(拆解)
        /// </summary>
        /// <param name="formulas">計算式作成</param>
        protected virtual void CleverWithSyntheticUnknit(IList <CleverCalculationFormula> formulas)
        {
            // 當前反推判定次數(一次推算內次數累加)
            int defeated = 0;

            CleverCalculationFormula cleverCalculation = new CleverCalculationFormula
            {
                Type           = (int)Synthetic.Unknit,
                ConfixFormulas = new List <Formula>(),
                Answer         = new List <int>()
            };

            while (1 == 1)
            {
                // 如果大於三次則認為此題無法作成繼續下一題
                if (defeated == INVERSE_NUMBER)
                {
                    cleverCalculation = null;
                    break;
                }

                cleverCalculation.ConfixFormulas.Clear();
                cleverCalculation.Answer.Clear();

                // 獲取一個待拆解的非整數(不包含各位為5的數)
                int unknitValue = CommonUtil.GetRandomNumber(10, 60, condition: _ => _ % 10 != 0 && _ % 10 != 5, getDefault: () => 46);
                // 獲取一個10以內的因數
                int factor = CommonUtil.GetRandomNumber(3, 9, condition: _ => _ != unknitValue % 10, getDefault: () => 5);

                // 數字按照位數分解
                int[] unknits = new int[2] {
                    unknitValue / 10, unknitValue % 10
                };
                // 距離整數的差異值
                int unknitDiff = unknits[1] >= 5 ? 10 - unknits[1] : unknits[1];

                // 結果值
                int answer = unknitValue * factor;
                // 用於設定待拆解因數的位置
                LeftOrRight leftOrRight = CommonUtil.GetRandomNumber(LeftOrRight.Left, LeftOrRight.Right);
                cleverCalculation.Answer.Add(answer);
                if (leftOrRight == LeftOrRight.Left)
                {
                    cleverCalculation.ConfixFormulas.Add(new Formula(unknitValue, factor, answer, SignOfOperation.Multiple));
                }
                else
                {
                    cleverCalculation.ConfixFormulas.Add(new Formula(factor, unknitValue, answer, SignOfOperation.Multiple));
                }

                StringBuilder express = new StringBuilder();
                // 加法拆解
                if (unknits[1] < 5)
                {
                    // eg: 12 * 5 = 10 * 5 + 2 * 5
                    express.AppendFormat(CultureInfo.CurrentCulture, "{0}*{1}+{2}*{3}", unknitValue - unknitDiff, factor, unknits[1], factor);
                }
                // 減法拆解
                else
                {
                    // eg: 18 * 5 = 20 * 5 - 2 * 5
                    express.AppendFormat(CultureInfo.CurrentCulture, "{0}*{1}-{2}*{3}", unknitValue + unknitDiff, factor, unknitDiff, factor);
                }

                // 計算式推導
                var calc = new ExpressArithmeticUtil();
                if (!calc.IsResult(express.ToString(), out int result))
                {
                    defeated++;
                    continue;
                }
                if (result != answer)
                {
                    defeated++;
                    continue;
                }
                // 加入推導出計算式集合
                calc.Formulas.ToList().ForEach(f => cleverCalculation.ConfixFormulas.Add(f));
                defeated = 0;

                break;
            }

            if (cleverCalculation != null)
            {
                formulas.Add(cleverCalculation);
            }
        }