在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
目录
学有所得
需求需求:任意1-10中的4个数字,使用加减乘除计算得出24结果的可能组合; 3、在任何一次计算中不能出现小数,
View Code
那需求该如何分析呢,怎么划分成小需求呢?一般来说我们都会通过案例来分析,比如:这个需求,我们使用传统的计算,假设我们已经有这四个数[3,4,8,6],可能会有如下组合: 方案:((4.0 + 8.0) * 6.0) / 3.0=24.0; 方案:(4.0 * 3.0) * (8.0 - 6.0) = 24.0; 我们暂时先分析这个几个方案,大家看到这里,可以先思考一下有什么规律,有什么规则; ....................................................................................................Thinking.............................. 从这些方案中,我们可以得出如下蹊跷之处: 不知道大家是不是和我发现的一样不,或者说有更多的发现;我认为不管什么发现都可以先列出来,然后在逐个去去除一些太离谱的发现; 我们继续分析需求,看看是否可以再次分解 从上面的需求中我们可以进一步进行分解 第一、如何获取四个数的所有排列组合? 获取所有基准代码: List<double[]> resultAllList = new List<double[]>(); List<double[]> list = new List<double[]>(); list.Add(array); list.Add(new double[] { array[1], array[2], array[3], array[0] }); list.Add(new double[] { array[2], array[3], array[0], array[1] }); list.Add(new double[] { array[3], array[0], array[1], array[2] });
获取每个基准的所有排列组合: /// <summary> /// 获取array的所有可能组合 /// </summary> /// <param name="list"></param> /// <param name="array"></param> public static void GetAllArray(List<double[]> list, double[] array) { if (!Exists(list, array)) { list.Add(array); } for (int i = 1; i < 4; i++) { double[] arrayCopy = DeepCopyByBin<double[]>(array); List<double[]> newList = GetArrayList(arrayCopy, i); newList.ForEach((item) => { if (!Exists(list, item)) { list.Add(item); } }); } } /// <summary> /// 获取array下标遇到i的位置左右组合 /// </summary> /// <param name="array"></param> /// <param name="i"></param> /// <returns></returns> public static List<double[]> GetArrayList(double[] array, int i) { List<double[]> list = new List<double[]>(); for (int j = i; j > 0; j--) { double temp = array[j]; array[j] = array[j - 1]; array[j - 1] = temp; list.Add(array); array = DeepCopyByBin<double[]>(array); } return list; } /// <summary> /// array是否存啊在list中 /// </summary> /// <param name="list"></param> /// <param name="array"></param> /// <returns></returns> public static bool Exists(List<double[]> list, double[] array) { bool isExist = false; for (int i = 0; i < list.Count; i++) { var item = list[i]; if (item[0] == array[0] && item[1] == array[1] && item[2] == array[2] && item[3] == array[3]) { isExist = true; break; } } return isExist; }
第二,对于算法法则该如何继续分析呢?我们可以继续使用举例 /// <summary> /// 计算array能算24点的所有组合,从左到右的顺序 /// </summary> /// <param name="array"></param> /// <returns></returns> public static int Caculate24Point(double[] array) { int count = 0; if (array.Length != 4) { throw new Exception("不是四个数"); } for (int i = 0; i < operators.Length; i++) { string op = operators[i]; String expressionStr = ""; double result = GetTwoNumCaculate(array[0], array[1], op); if (!IsValidResult(result)) { continue; } expressionStr = $"({array[0]}{op}{array[1]})"; for (int j = 0; j < operators.Length; j++) { string op2 = operators[j]; double result1 = GetTwoNumCaculate(result, array[2], op2); if (!IsValidResult(result1)) { continue; } String expressionStr2 = $"({expressionStr}{op2}{array[2]})"; for (int k = 0; k < operators.Length; k++) { string op3 = operators[k]; double result2 = GetTwoNumCaculate(result1, array[3], op3); String expressionStr3 = $"{expressionStr2}{op3}{array[3]}";//String.format("%s %s %s", expressionStr2, op3, array[3]); if (result2 == 24.0d) { count++; Console.WriteLine($"方案:{expressionStr3}={result2}"); } } } } return count; }
2、两两组合,思路和上面有些相似, 前两个数的任意计算结果1, /// <summary> /// 计算array能算24点的所有组合 ,两两组合 /// </summary> /// <param name="array"></param> /// <returns></returns> public static int Caculate24Point2(double[] array) { int count = 0; if (array.Length != 4) { throw new Exception("不是四个数"); } for (int i = 0; i < operators.Length; i++) { string op = operators[i]; double result1 = GetTwoNumCaculate(array[0], array[1], op); if (!IsValidResult(result1)) { continue; } String expressionStr1 = $"({array[0]}{op}{array[1]})"; for (int j = 0; j < operators.Length; j++) { string op2 = operators[j]; double result2 = GetTwoNumCaculate(array[2], array[3], op2); if (!IsValidResult(result2)) { continue; } String expressionStr2 = $"({array[2]}{op2}{array[3]})"; for (int k = 0; k < operators.Length; k++) { string op3 = operators[k]; double result3 = GetTwoNumCaculate(result1, result2, op3); String expressionStr3 = $"{expressionStr1} {op3} {expressionStr2}"; if (result3 == 24.0d) { count++; Console.WriteLine($"方案: {expressionStr3} = {result3}"); } } } } return count; }
某一种四个数的所有运算排列通过上面的方式我们可以全部获取,分析到此,我觉得代码可以落地,当然,如果你觉得还不够清晰,可以继续分析,直到自己清晰为止,这里我只是提供分解需求的思路而已;在软件工程中,我们必定先分析需求,然后分解需求,我们有四色分析方式,我们还有DDD领域的分析方式等,都是需要通过逐步分解成更小的需求来反复验证的;
到目前为止我们可以得出如下思维导图
把各种子孙需求,通过组合编排,最终成为一个完整的大需求解决方案最后,我们把每个小的需求加上一些规则逻辑组合成完整的大需求,我们暂时叫做编排吧;
到目前为止是否完整呢?其实还差一点,任意的1-10的数字从哪里获取,不过需求没有明确,可以是用户输入,数据库获取,其他接口的传入,我们这里就定位用户输入吧 获取用户输入代码如下: double[] array = new double[4]; int index = 0; while (index < 4) { Console.WriteLine(String.Format("请输入第{0}个1-10的整数", index + 1)); String tempNumStr = Console.ReadLine(); if (!int.TryParse(tempNumStr, out int tmpNum)) { Console.WriteLine("你输入的不是一个整数"); continue; } if (tmpNum < 0 || tmpNum > 10) { Console.WriteLine("你输入的数字不是1-10的数字"); continue; } array[index++] = (double)tmpNum; } Console.WriteLine($"你输入的4个1-10的整数为{array[0]},{array[1]},{array[2]},{array[3]}");
最终完整代码如下: using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.Serialization.Formatters.Binary; using System.Text; using System.Threading.Tasks; namespace Point24Caculate { class Program { private static string[] operators = new string[] { "+", "-", "*", "/" }; static void Main(string[] args) { double[] array = new double[4]; int index = 0; while (index < 4) { Console.WriteLine(String.Format("请输入第{0}个1-10的整数", index + 1)); String tempNumStr = Console.ReadLine(); if (!int.TryParse(tempNumStr, out int tmpNum)) { Console.WriteLine("你输入的不是一个整数"); continue; } if (tmpNum < 0 || tmpNum > 10) { Console.WriteLine("你输入的数字不是1-10的数字"); continue; } array[index++] = (double)tmpNum; } Console.WriteLine($"你输入的4个1-10的整数为{array[0]},{array[1]},{array[2]},{array[3]}"); Console.WriteLine("结果如下:"); List<double[]> resultAllList = new List<double[]>(); List<double[]> list = new List<double[]>(); list.Add(array); list.Add(new double[] { array[1], array[2], array[3], array[0] }); list.Add(new double[] { array[2], array[3], array[0], array[1] }); list.Add(new double[] { array[3], array[0], array[1], array[2] }); for (int i = 0; i < list.Count; i++) { GetAllArray(resultAllList, DeepCopyByBin(list[i])); } int sum = 0; resultAllList.ForEach(itemArray => { sum += Caculate24Point(itemArray); sum += Caculate24Point2(itemArray); }); Console.WriteLine("总共方案数量:" + sum); Console.ReadLine(); } /// <summary> /// 获取array的所有可能组合 /// </summary> /// <param name="list"></param> /// <param name="array"></param> public static void GetAllArray(List<double[]> list, double[] array) { if (!Exists(list, array)) { list.Add(array); } for (int i = 1; i < 4; i++) { double[] arrayCopy = DeepCopyByBin<double[]>(array); List<double[]> newList = GetArrayList(arrayCopy, i); newList.ForEach((item) => { if (!Exists(list, item)) { list.Add(item); } }); } } /// <summary> /// 获取array下标遇到i的位置左右组合 /// </summary> /// <param name="array"></param> /// <param name="i"></param> /// <returns></returns> public static List<double[]> GetArrayList(double[] array, int i) { List<double[]> list = new List<double[]>(); for (int j = i; j > 0; j--) { double temp = array[j]; array[j] = array[j - 1]; array[j - 1] = temp; list.Add(array); array = DeepCopyByBin<double[]>(array); } return list; } /// <summary> /// array是否存啊在list中 /// </summary> /// <param name="list"></param> /// <param name="array"></param> /// <returns></returns> public static bool Exists(List<double[]> list, double[] array) { bool isExist = false; for (int i = 0; i < list.Count; i++) { var item = list[i]; if (item[0] == array[0] && item[1] == array[1] && item[2] == array[2] && item[3] == array[3]) { isExist = true; break; } } return isExist; } /// <summary> /// 深拷贝 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="obj"></param> /// <returns></returns> public static T DeepCopyByBin<T>(T obj) { object retval; using (MemoryStream ms = new MemoryStream()) { BinaryFormatter bf = new BinaryFormatter(); //序列化成流 bf.Serialize(ms, obj); ms.Seek(0, SeekOrigin.Begin); //反序列化成对象 retval = bf.Deserialize(ms); ms.Close(); } return (T)retval; } /// <summary> /// 计算array能算24点的所有组合,从左到右的顺序 /// </summary> /// <param name="array"></param> /// <returns></returns> public static int Caculate24Point(double[] array) { int count = 0; if (array.Length != 4) { throw new Exception("不是四个数"); } for (int i = 0; i < operators.Length; i++) { string op = operators[i]; String expressionStr = ""; double result = GetTwoNumCaculate(array[0], array[1], op); if (!IsValidResult(result)) { continue; } expressionStr = $"({array[0]}{op}{array[1]})"; for (int j = 0; j < operators.Length; j++) { string op2 = operators[j]; double result1 = GetTwoNumCaculate(result, array[2], op2); if (!IsValidResult(result1)) { continue; } String expressionStr2 = $"({expressionStr}{op2}{array[2]})"; for (int k = 0; k < operators.Length; k++) { string op3 = operators[k]; double result2 = GetTwoNumCaculate(result1, array[3], op3); String expressionStr3 = $"{expressionStr2}{op3}{array[3]}";//String.format("%s %s %s", expressionStr2, op3, array[3]); if (result2 == 24.0d) { count++; Console.WriteLine($"方案:{expressionStr3}={result2}"); } } } } return count; } /// <summary> /// 计算array能算24点的所有组合 ,两两组合 /// </summary> /// <param name="array"></param> /// <returns></returns> public static int Caculate24Point2(double[] array) { int count = 0; if (array.Length != 4) { throw new Exception("不是四个数"); } for (int i = 0; i < operators.Length; i++) { string op = operators[i]; double result1 = GetTwoNumCaculate(array[0], array[1], op); if (!IsValidResult(result1)) { continue; } String expressionStr1 = $"({array[0]}{op}{array[1]})"; for (int j = 0; j < operators.Length; j++) { string op2 = operators[j]; double result2 = GetTwoNumCaculate(array[2], array[3], op2); if (!IsValidResult(result2)) { continue; } String expressionStr2 = $"({array[2]}{op2}{array[3]})"; for (int k = 0; k < operators.Length; k++) { string op3 = operators[k]; double result3 = GetTwoNumCaculate(result1, result2, op3); String expressionStr3 = $"{expressionStr1} {op3} {expressionStr2}"; if (result3 == 24.0d) { count++; Console.WriteLine($"方案: {expressionStr3} = {result3}"); } } } } return count; } /// <summary> /// 是否为合法的计算结果 /// </summary> /// <param name="result"></param> /// <returns></returns> public static bool IsValidResult(double result) { if (result < 1) { return false; } return result == Math.Floor(result); } private static double GetTwoNumCaculate(double num1, double num2, string operatorStr) { switch (operatorStr) { case "+": return num1 + num2; case "-": return num1 - num2; case "*": return num1 * num2; case "/" |
请发表评论