/// <summary> /// 乘法巧算 /// </summary> /// <param name="formulas">計算式作成</param> /// <remarks> /// 計算式構成樣例: 36 = (?) X 6 = (?) X 2 = 4 X (?) /// 結果列:6, 18, 9 /// </remarks> protected virtual void CleverWithMultiple(IList <CleverCalculationFormula> formulas) { CleverCalculationFormula cleverCalculation = new CleverCalculationFormula { Type = (int)TopicType.Multiple, ConfixFormulas = new List <Formula>(), Answer = new List <int>() }; // 乘法算式序列(取得隨機數後執行Check回調預判其是否可用) var list = GetMultipleSyntagmaticOrdering(formulas); if (!list.Any()) { return; } int seq = 1; // 從乘法算式序列中隨機選擇3個算式(不重複) while (seq <= 3) { var formula = CommonUtil.GetRandomNumber(list); cleverCalculation.Answer.Add(formula.Gap == GapFilling.Left ? formula.LeftParameter : formula.RightParameter); cleverCalculation.ConfixFormulas.Add(formula); list.Remove(formula); seq++; } formulas.Add(cleverCalculation); }
/// <summary> /// 減法巧算 /// </summary> /// <param name="formulas">計算式作成</param> protected virtual void CleverWithSubtraction(IList <CleverCalculationFormula> formulas) { CleverCalculationFormula cleverCalculation = new CleverCalculationFormula { Type = (int)TopicType.Plus, ConfixFormulas = new List <Formula>(), Answer = new List <int>() }; // 獲取兩個隨機非整數 // 減數的個位是大於等於3的兩位數 var right = CommonUtil.GetRandomNumber(20, 60, condition: _ => _ % 10 != 0 && _ % 10 >= 3, getDefault: () => 23); // 被減數需要滿足借位計算 var left = CommonUtil.GetRandomNumber(50, 99, condition: _ => _ % 10 != 0 && _ > right && _ % 10 < right % 10, getDefault: () => 51); var answer = left - right; cleverCalculation.ConfixFormulas.Add(new Formula(left, right, answer, SignOfOperation.Subtraction)); cleverCalculation.Answer.Add(answer); // 數字按照位數分解 int[] lefts = new int[2] { left / 10, left % 10 }; int[] rights = new int[2] { right / 10, right % 10 }; // 距離整數的差異值 int leftDiff = lefts[1] >= 5 ? 10 - lefts[1] : lefts[1]; int rightDiff = rights[1] >= 5 ? 10 - rights[1] : rights[1]; // eg: 51 - 19 = 50 - 18 || 52 - 20 if (lefts[1] + rights[1] == 10) { cleverCalculation.ConfixFormulas.Add(new Formula(left - leftDiff, right - leftDiff, answer, SignOfOperation.Subtraction)); cleverCalculation.ConfixFormulas.Add(new Formula(left + rightDiff, right + rightDiff, answer, SignOfOperation.Subtraction)); } // eg: 51 - 12 = 50 - 11 else if (leftDiff < rightDiff) { cleverCalculation.ConfixFormulas.Add(new Formula(left - leftDiff, right - leftDiff, answer, SignOfOperation.Subtraction)); } // eg: 53 - 19 = 54 - 20 else if (leftDiff > rightDiff) { cleverCalculation.ConfixFormulas.Add(new Formula(left + rightDiff, right + rightDiff, answer, SignOfOperation.Subtraction)); } formulas.Add(cleverCalculation); }
/// <summary> /// 加法巧算 /// </summary> /// <param name="formula">計算式</param> /// <returns></returns> private string CleverWithPlus(CleverCalculationFormula formula) { StringBuilder html = new StringBuilder(); StringBuilder answer = new StringBuilder(); string flag = "topic"; int controlIndex = 0; formula.ConfixFormulas.ToList().ForEach(d => { if ("topic".Equals(flag)) { html.AppendFormat(LABEL_HTML_FORMAT, d.LeftParameter); html.AppendFormat(LABEL_HTML_FORMAT, d.Sign.ToOperationUnicode()); html.AppendFormat(LABEL_HTML_FORMAT, d.RightParameter); } if ("result".Equals(flag)) { html.AppendLine(string.Format(LABEL_HTML_FORMAT, SignOfCompare.Equal.ToSignOfCompareUnicode())); html.AppendLine(GetHtml(GapFilling.Left, d.LeftParameter, GapFilling.Left, _parentIndex, controlIndex++)); html.AppendLine(string.Format(LABEL_HTML_FORMAT, d.Sign.ToOperationUnicode())); html.AppendLine(GetHtml(GapFilling.Right, d.RightParameter, GapFilling.Right, _parentIndex, controlIndex++)); answer.AppendFormat("{0};", d.LeftParameter); answer.AppendFormat("{0};", d.RightParameter); } flag = "result"; }); html.AppendLine(string.Format(LABEL_HTML_FORMAT, SignOfCompare.Equal.ToSignOfCompareUnicode())); html.AppendLine(GetHtml(GapFilling.Answer, formula.Answer[0], GapFilling.Answer, _parentIndex, controlIndex++)); answer.AppendFormat("{0}", formula.Answer[0]); // 用於結果驗證 html.AppendFormat(ANSWER_HTML_FORMAT, _parentIndex.ToString().PadLeft(2, '0'), Base64.EncodeBase64(answer.ToString())); return(html.ToString()); }
/// <summary> /// 綜合題型巧算(拆解) /// </summary> /// <param name="formula">計算式</param> /// <returns></returns> private string CleverWithSyntheticUnknit(CleverCalculationFormula formula) { StringBuilder html = new StringBuilder(); StringBuilder answer = new StringBuilder(); html.AppendFormat(LABEL_HTML_FORMAT, formula.ConfixFormulas[0].LeftParameter).AppendLine(); html.AppendFormat(LABEL_HTML_FORMAT, formula.ConfixFormulas[0].Sign.ToOperationUnicode()).AppendLine(); html.AppendFormat(LABEL_HTML_FORMAT, formula.ConfixFormulas[0].RightParameter).AppendLine(); int controlIndex = 0; html.AppendLine(string.Format(LABEL_HTML_FORMAT, SignOfCompare.Equal.ToSignOfCompareUnicode())); html.AppendLine(GetHtml(GapFilling.Left, formula.ConfixFormulas[1].LeftParameter, GapFilling.Left, _parentIndex, controlIndex++)); html.AppendLine(string.Format(LABEL_HTML_FORMAT, formula.ConfixFormulas[1].Sign.ToOperationUnicode())); html.AppendLine(GetHtml(GapFilling.Right, formula.ConfixFormulas[1].RightParameter, GapFilling.Right, _parentIndex, controlIndex++)); html.AppendLine(string.Format(LABEL_HTML_FORMAT, formula.ConfixFormulas[3].Sign.ToOperationUnicode())); html.AppendLine(GetHtml(GapFilling.Left, formula.ConfixFormulas[2].LeftParameter, GapFilling.Left, _parentIndex, controlIndex++)); html.AppendLine(string.Format(LABEL_HTML_FORMAT, formula.ConfixFormulas[2].Sign.ToOperationUnicode())); html.AppendLine(GetHtml(GapFilling.Right, formula.ConfixFormulas[2].RightParameter, GapFilling.Right, _parentIndex, controlIndex++)); html.AppendLine(string.Format(LABEL_HTML_FORMAT, SignOfCompare.Equal.ToSignOfCompareUnicode())); html.AppendLine(GetHtml(GapFilling.Answer, formula.Answer[0], GapFilling.Answer, _parentIndex, controlIndex++)); answer.AppendFormat("{0};", formula.ConfixFormulas[1].LeftParameter); answer.AppendFormat("{0};", formula.ConfixFormulas[1].RightParameter); answer.AppendFormat("{0};", formula.ConfixFormulas[2].LeftParameter); answer.AppendFormat("{0};", formula.ConfixFormulas[2].RightParameter); answer.AppendFormat("{0}", formula.Answer[0]); // 用於結果驗證 html.AppendFormat(ANSWER_HTML_FORMAT, _parentIndex.ToString().PadLeft(2, '0'), Base64.EncodeBase64(answer.ToString())); return(html.ToString()); }
/// <summary> /// 乘法巧算 /// </summary> /// <param name="formula">計算式</param> /// <returns></returns> private string CleverWithMultiple(CleverCalculationFormula formula) { StringBuilder html = new StringBuilder(); StringBuilder answer = new StringBuilder(); html.AppendFormat(LABEL_HTML_FORMAT, formula.ConfixFormulas[0].Answer); int controlIndex = 0; formula.ConfixFormulas.ToList().ForEach(d => { html.AppendLine(string.Format(LABEL_HTML_FORMAT, SignOfCompare.Equal.ToSignOfCompareUnicode())); html.AppendLine(GetHtml(d.Gap, d.LeftParameter, GapFilling.Left, _parentIndex, controlIndex++)); html.AppendLine(string.Format(LABEL_HTML_FORMAT, SignOfOperation.Multiple.ToOperationUnicode())); html.AppendLine(GetHtml(d.Gap, d.RightParameter, GapFilling.Right, _parentIndex, controlIndex++)); }); formula.Answer.ForEach(d => answer.AppendFormat("{0};", d)); answer.Length -= 1; // 用於結果驗證 html.AppendFormat(ANSWER_HTML_FORMAT, _parentIndex.ToString().PadLeft(2, '0'), Base64.EncodeBase64(answer.ToString())); return(html.ToString()); }
/// <summary> /// 減法巧算 /// </summary> /// <param name="formula">計算式</param> /// <returns></returns> private string CleverWithSubtraction(CleverCalculationFormula formula) { return(CleverWithPlus(formula)); }
/// <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); } }
/// <summary> /// 加法巧算 /// </summary> /// <param name="formulas">計算式作成</param> /// <remarks> /// 計算式構成樣例: 57 + 78 = (?) + (?) = (?) /// 結果列:135 /// </remarks> protected virtual void CleverWithPlus(IList <CleverCalculationFormula> formulas) { CleverCalculationFormula cleverCalculation = new CleverCalculationFormula { Type = (int)TopicType.Plus, ConfixFormulas = new List <Formula>(), Answer = new List <int>() }; // 獲取兩個隨機非整數 var left = CommonUtil.GetRandomNumber(10, 99, _ => _ % 10 != 0, () => 11); var right = CommonUtil.GetRandomNumber(10, 99, _ => _ % 10 != 0 && _ != left, () => 12); var answer = left + right; cleverCalculation.ConfixFormulas.Add(new Formula(left, right, answer, SignOfOperation.Plus)); cleverCalculation.Answer.Add(answer); // 數字按照位數分解 int[] lefts = new int[2] { left / 10, left % 10 }; int[] rights = new int[2] { right / 10, right % 10 }; // 距離整數的差異值 int leftDiff = lefts[1] >= 5 ? 10 - lefts[1] : lefts[1]; int rightDiff = rights[1] >= 5 ? 10 - rights[1] : rights[1]; // eg: 58 + 57 => 60 + 59 // eg: 58 + 12 => 60 + 10 // eg: 55 + 25 => 60 + 20 || 50 + 30 if (lefts[1] >= 5 && (leftDiff < rightDiff || lefts[1] + rights[1] == 10)) { // 左邊的值向上化整 cleverCalculation.ConfixFormulas.Add(new Formula(left + leftDiff, right - leftDiff, answer, SignOfOperation.Plus)); // 左右兩邊的值向上化整 if (lefts[1] == 5 && rights[1] == 5) { cleverCalculation.ConfixFormulas.Add(new Formula(left - leftDiff, right + leftDiff, answer, SignOfOperation.Plus)); } } // eg: 58 + 48 => 60 + 46 || 56 + 50 else if (lefts[1] > 5 && lefts[1] == rights[1]) { // 左右兩邊的值向上化整 cleverCalculation.ConfixFormulas.Add(new Formula(left + leftDiff, right - leftDiff, answer, SignOfOperation.Plus)); cleverCalculation.ConfixFormulas.Add(new Formula(left - rightDiff, right + rightDiff, answer, SignOfOperation.Plus)); } // eg: 57 + 69 => 56 + 70 // eg: 57 + 61 => 58 + 60 // eg: 55 + 21 => 56 + 20 // eg: 55 + 28 => 57 + 30 else if (lefts[1] >= 5 && leftDiff > rightDiff) { if (rights[1] >= 5) { // 右邊的值向上化整 cleverCalculation.ConfixFormulas.Add(new Formula(left - rightDiff, right + rightDiff, answer, SignOfOperation.Plus)); } else { // 右邊的值向下化整 cleverCalculation.ConfixFormulas.Add(new Formula(left + rightDiff, right - rightDiff, answer, SignOfOperation.Plus)); } } // eg: 51 + 52 => 50 + 53 // eg: 51 + 59 => 50 + 60 // eg: 55 + 59 => 54 + 60 else if (lefts[1] <= 5 && (leftDiff < rightDiff || lefts[1] + rights[1] == 10)) { // 左邊的值向下化整 cleverCalculation.ConfixFormulas.Add(new Formula(left - lefts[1], right + lefts[1], answer, SignOfOperation.Plus)); } // eg: 51 + 41 => 50 + 42 || 52 + 40 else if (lefts[1] < 5 && lefts[1] == rights[1]) { // 左右兩邊的值向下化整 cleverCalculation.ConfixFormulas.Add(new Formula(left - lefts[1], right + lefts[1], answer, SignOfOperation.Plus)); cleverCalculation.ConfixFormulas.Add(new Formula(left + lefts[1], right - rights[1], answer, SignOfOperation.Plus)); } // eg: 54 + 61 => 55 + 60 // eg: 54 + 69 => 53 + 70 // eg: 55 + 33 => 58 + 30 else if (lefts[1] <= 5 && leftDiff > rightDiff) { if (rights[1] >= 5) { // 右邊的值向上化整 cleverCalculation.ConfixFormulas.Add(new Formula(left - rightDiff, right + rightDiff, answer, SignOfOperation.Plus)); } else { // 右邊的值向下化整 cleverCalculation.ConfixFormulas.Add(new Formula(left + rights[1], right - rights[1], answer, SignOfOperation.Plus)); } } // eg: 55 + 25 => 50 + 30 || 60 + 20 else if (lefts[1] == 5 && rights[1] == 5) { // 左右兩邊的值均可向下或者向下化整 cleverCalculation.ConfixFormulas.Add(new Formula(left - 5, right + 5, answer, SignOfOperation.Plus)); cleverCalculation.ConfixFormulas.Add(new Formula(left + 5, right - 5, answer, SignOfOperation.Plus)); } formulas.Add(cleverCalculation); }