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