目录

  1. 需求;
  2. 需求该如何分析呢,怎么划分成小需求呢?
  3. 如何把小需求编排成完整需求;

学有所得

  1. 学会分析需求,由哪些组成(规则,逻辑等);
  2. 能把的需求分解成很多子需求、或孙需求、或童孙需求,直到每个需求很清晰可实施地为止
  3. 学会把各种子孙需求,通过组合编排,最终成为一个完整的大需求解决方案

需求

需求:任意1-10中的4个数字,使用加减乘除计算得出24结果的可能组合;
通过初步分析,我们可以得到如下规则:
规则:1、任意1-10中的4个数字;
2、使用加减乘除计算得出24;

3、在任何一次计算中不能出现小数,
比如:(4.0 + 8.0) / (3.0 / 6.0) = 24.0,这种是不算的,虽然最终结果是24,因为3/6=0.5;(8.0 / 3.0) * (4.0 + 5.0) = 24.0,虽然最终为24,但是在第一步结果却是小数,所以不成立;代码如下

    /*** 是否为合法的计算结果* @param result* @return*/public  static  boolean isValidResult(double result){if (result<1){return  false;}return  result == Math.floor(result);}

View Code

4、整个运算中应该使用double类型,因为整数相除,使用int类型,在计算机中,会把余数抹掉,直接取整,这样就会造成结果不正确;

那需求该如何分析呢,怎么划分成小需求呢?

一般来说我们都会通过案例来分析,比如:这个需求,我们使用传统的计算,假设我们已经有这四个数[3,4,8,6],可能会有如下组合:

方案:((4.0 + 8.0) * 6.0) / 3.0=24.0;
方案:((3.0 * 4.0) - 8.0) * 6.0=24.0;
方案:((8.0 - 6.0) * 3.0) * 4.0=24.0;
方案:((4.0 + 8.0) / 3.0) * 6.0=24.0;

方案:(4.0 * 3.0) * (8.0 - 6.0) = 24.0;
方案:(6.0 / 3.0) * (4.0 + 8.0) = 24.0;

我们暂时先分析这个几个方案,大家看到这里,可以先思考一下有什么规律,有什么规则;

....................................................................................................Thinking..............................

从这些方案中,我们可以得出如下蹊跷之处:
1、所有的方案中,都在这四个数的所有可能排列组合中(我记忆之中,应该是高中数学的知识点);
2、我们可以把计算法则归纳为两种,所有的都可以归纳到一下两种中去;
第一、从左到右的依次计算;
第二、两两组合,前两个数计算结果和后两个数的计算结果再次计算;
第三、每个方案都有3个运算符;

不知道大家是不是和我发现的一样不,或者说有更多的发现;我认为不管什么发现都可以先列出来,然后在逐个去去除一些太离谱的发现;
我们再继续顺藤摸瓜,到此我们可以把需求分解如下:

我们继续分析需求,看看是否可以再次分解

从上面的需求中我们可以进一步进行分解

第一、如何获取四个数的所有排列组合?
1、举例,我们继续使用案列来分析,比如 [3,4,8,6]
[3,4,8,6](基准)
[4,3,8,6](第二和第一调换)
[3,8,4,6] [8,3,4,6](第三和第二调换,第二和第一调换)
[3,4,6,8] [3,6,4,8] [6,3,4,8] (第四和第三调换, 第三和第二调换,第二和第一调换)
这样是不是所有的排列组合呢?显然不是?因为还有三种基准进行上面的排列组合,也就是上面每行最后一列
[4,3,8,6](基准2)
[8,3,4,6](基准3)
[6,3,4,8](基准4)
2、通过上面的举例,我们就可以先获取所有的基准组合;
3、通过上面,我们可以知道每种基准的所有组合;
4、通过上面的方法获取的组合会有重复,需要前需要去重;
这样我们就能获取4个数的所有排列组合;我感觉这种获取所有排列组合的算法很笨重(有没有感觉有点想冒泡排序),不优雅,肯定有更优的方案,只是我不知道而已,如果知道的可以留言,谢谢;
所有排列分析到此,是不是还需要继续分析,可以继续思考;本人感觉可以落地了;如果觉得需要继续分析的,可以继续分解,知道自己很清晰,知道怎么干为止(这个因人而异);请看代码;

获取所有基准代码:

double[] array = {3, 4, 6, 8};List<double[]> resultAllList = new ArrayList<>();List<double[]> list = new ArrayList<>();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]});

View Code

获取每个基准的所有排列组合:

    /*** 获取array的所有可能组合** @param list* @param array*/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 = Arrays.copyOf(array, array.length);List<double[]> newList = getArrayList(arrayCopy, i);Iterator<double[]> iterator = newList.iterator();while (iterator.hasNext()) {double[] temp = iterator.next();if (!exists(list, temp)) {list.add(temp);}}}}/*** 获取array下标遇到i的位置左右组合** @param array* @param i* @return*/public static List<double[]> getArrayList(double[] array, int i) {List<double[]> list = new ArrayList<>();for (int j = i; j > 0; j--) {double temp = array[j];array[j] = array[j - 1];array[j - 1] = temp;list.add(array);array = Arrays.copyOf(array, array.length);}return list;}

View Code

第二,对于算法法则该如何继续分析呢?我们可以继续使用举例
从上面随意获取一种排列组合,比如:[3,4,8,6]
1、从左到右的组合,在上面四个数字中,任意两个数中,我们可以有+,- ,*,/这四种算法,这又是一种计算的所有排列组合,并把结果和24对比,如果相等,那就是可行方案;
那我们是不是继续使用上面获取组合的方式呢?显然不是,这里关键点在于:任意两个数中都有+-*/的算法,这里我们可以使用三个for循环解决;
举例:((3.0 * 4.0) - 8.0) * 6.0=24.0;

/*** 计算array能算24点的所有组合,从左到右的顺序** @param* @throws Exception*/public static int caculate24Point(double[] array) throws Exception {int count = 0;if (array.length != 4) {throw new Exception("不是四个数");}for (String op : operators) {String expressionStr = "";double result = getTwoNumCaculate(array[0], array[1], op);if (!isValidResult(result)){continue;}expressionStr = String.format("(%s %s %s)", array[0], op, array[1]);for (String op2 : operators) {double result1 = getTwoNumCaculate(result, array[2], op2);if (!isValidResult(result1)){continue;}String expressionStr2 = String.format("(%s %s %s)", expressionStr, op2, array[2]);for (String op3 : operators) {double result2 = getTwoNumCaculate(result1, array[3], op3);String expressionStr3 = String.format("%s %s %s", expressionStr2, op3, array[3]);if (result2 == 24.0d) {count++;System.out.println(String.format("方案:%s=%s", expressionStr3, result2));}}}}return count;}

View Code

2、两两组合,思路和上面有些相似,

前两个数的任意计算结果1,
后两个数的任意计算结果2,
结果1和结果2的任意计算结果3,
结果3和24对比,如果相等,那就是可行方案;
举例:(3.0 * 4.0) * (8.0 - 6.0) = 24.0;

/*** 计算array能算24点的所有组合 ,两两组合** @param array* @return* @throws Exception*/public static int caculate24Point2(double[] array) throws Exception {int count = 0;if (array.length != 4) {throw new Exception("不是四个数");}for (String op : operators) {double result1 = getTwoNumCaculate(array[0], array[1], op);if (!isValidResult(result1)){continue;}String expressionStr1 = String.format("(%s %s %s)", array[0], op, array[1]);for (String op2 : operators) {double result2 = getTwoNumCaculate(array[2], array[3], op2);if (!isValidResult(result2)){continue;}String expressionStr2 = String.format("(%s %s %s)", array[2], op2, array[3]);for (String op3 : operators) {double result3 = getTwoNumCaculate(result1, result2, op3);String expressionStr3 = String.format("%s %s %s", expressionStr1, op3, expressionStr2);if (result3 == 24.0d) {count++;System.out.println(String.format("方案: %s = %s", expressionStr3, result3));}}}}return count;}

View Code

某一种四个数的所有运算排列通过上面的方式我们可以全部获取,分析到此,我觉得代码可以落地,当然,如果你觉得还不够清晰,可以继续分析,直到自己清晰为止,这里我只是提供分解需求的思路而已;在软件工程中,我们必定先分析需求,然后分解需求,我们有四色分析方式,我们还有DDD领域的分析方式等,都是需要通过逐步分解成更小的需求来反复验证的;

到目前为止我们可以得出如下思维导图

把各种子孙需求,通过组合编排,最终成为一个完整的大需求解决方案

最后,我们把每个小的需求加上一些规则逻辑组合成完整的大需求,我们暂时叫做编排吧;
这里其实也是一个难点,很多人希望一次性把代码写完整,写正确,其实这种思路是不正确的,这样只会增加代码的难度,一次性能把代码写的有多完整多正确,这个跟每个人的编程经验熟练度有关;
不管编程多牛,从无到有的敲代码方向不是一次性把左右的代码完成,重点方向把核心逻辑思路编写上,其次才逐步把一些细节逻辑规则加上去,这个就和我们小时候学画画一样,画一颗树先画主干然后画叶子最后添加果子和花之类的;

到目前为止是否完整呢?其实还差一点,任意的1-10的数字从哪里获取,不过需求没有明确,可以是用户输入,数据库获取,其他接口的传入,我们这里就定位用户输入吧

获取用户输入代码如下:

 double[] array = new double[4];int index=0;Scanner scanner=new Scanner(System.in);while (index<4){System.out.println(String.format("请输入第%s个1-10的整数",index+1));String tempNumStr=scanner.nextLine();if(!StringUtils.isNumeric(tempNumStr)){System.out.println("你输入的不是一个整数");continue;}double tmpNum=Double.valueOf(tempNumStr);if (tmpNum<0 || tmpNum>10){System.out.println("你输入的数字不是1-10的数字");continue;}array[index++]=tmpNum;}System.out.println(String.format("你输入的4个1-10的整数为%s,%s,%s,%s",array[0],array[1],array[2],array[3]));

View Code

最终完整代码如下:

import org.apache.commons.lang3.StringUtils;import java.util.*;/*** Author:* Date:*/
public class Point24Caculator {/*** 计算24点中可以到的操作*/private static String[] operators = {"+", "-", "*", "/"};public static void main(String[] args) throws Exception {double[] array = new double[4];int index=0;Scanner scanner=new Scanner(System.in);while (index<4){System.out.println(String.format("请输入第%s个1-10的整数",index+1));String tempNumStr=scanner.nextLine();if(!StringUtils.isNumeric(tempNumStr)){System.out.println("你输入的不是一个整数");continue;}double tmpNum=Double.valueOf(tempNumStr);if (tmpNum<0 || tmpNum>10){System.out.println("你输入的数字不是1-10的数字");continue;}array[index++]=tmpNum;}System.out.println(String.format("你输入的4个1-10的整数为%s,%s,%s,%s",array[0],array[1],array[2],array[3]));System.out.println("结果如下:");List<double[]> resultAllList = new ArrayList<>();List<double[]> list = new ArrayList<>();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.size(); i++) {getAllArray(resultAllList, Arrays.copyOf(list.get(i), list.get(i).length));}int sum = 0;Iterator<double[]> iterator = resultAllList.iterator();while (iterator.hasNext()) {double[] tempArray = iterator.next();sum += caculate24Point(tempArray);sum += caculate24Point2(tempArray);}System.out.println("总共方案数量:" + sum);}/*** 获取array的所有可能组合** @param list* @param array*/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 = Arrays.copyOf(array, array.length);List<double[]> newList = getArrayList(arrayCopy, i);Iterator<double[]> iterator = newList.iterator();while (iterator.hasNext()) {double[] temp = iterator.next();if (!exists(list, temp)) {list.add(temp);}}}}/*** 获取array下标遇到i的位置左右组合** @param array* @param i* @return*/public static List<double[]> getArrayList(double[] array, int i) {List<double[]> list = new ArrayList<>();for (int j = i; j > 0; j--) {double temp = array[j];array[j] = array[j - 1];array[j - 1] = temp;list.add(array);array = Arrays.copyOf(array, array.length);}return list;}/*** array是否存啊在list中** @param list* @param array* @return*/public static boolean exists(List<double[]> list, double[] array) {Iterator<double[]> iterator = list.iterator();while (iterator.hasNext()) {double[] tmpArray = iterator.next();if (tmpArray[0] == array[0] && tmpArray[1] == array[1] && tmpArray[2] == array[2] && tmpArray[3] == array[3]) {return true;}}return false;}/*** 计算array能算24点的所有组合,从左到右的顺序** @param* @throws Exception*/public static int caculate24Point(double[] array) throws Exception {int count = 0;if (array.length != 4) {throw new Exception("不是四个数");}for (String op : operators) {String expressionStr = "";double result = getTwoNumCaculate(array[0], array[1], op);if (!isValidResult(result)){continue;}expressionStr = String.format("(%s %s %s)", array[0], op, array[1]);for (String op2 : operators) {double result1 = getTwoNumCaculate(result, array[2], op2);if (!isValidResult(result1)){continue;}String expressionStr2 = String.format("(%s %s %s)", expressionStr, op2, array[2]);for (String op3 : operators) {double result2 = getTwoNumCaculate(result1, array[3], op3);String expressionStr3 = String.format("%s %s %s", expressionStr2, op3, array[3]);if (result2 == 24.0d) {count++;System.out.println(String.format("方案:%s=%s", expressionStr3, result2));}}}}return count;}/*** 计算array能算24点的所有组合 ,两两组合** @param array* @return* @throws Exception*/public static int caculate24Point2(double[] array) throws Exception {int count = 0;if (array.length != 4) {throw new Exception("不是四个数");}for (String op : operators) {double result1 = getTwoNumCaculate(array[0], array[1], op);if (!isValidResult(result1)){continue;}String expressionStr1 = String.format("(%s %s %s)", array[0], op, array[1]);for (String op2 : operators) {double result2 = getTwoNumCaculate(array[2], array[3], op2);if (!isValidResult(result2)){continue;}String expressionStr2 = String.format("(%s %s %s)", array[2], op2, array[3]);for (String op3 : operators) {double result3 = getTwoNumCaculate(result1, result2, op3);String expressionStr3 = String.format("%s %s %s", expressionStr1, op3, expressionStr2);if (result3 == 24.0d) {count++;System.out.println(String.format("方案: %s = %s", expressionStr3, result3));}}}}return count;}/*** 是否为合法的计算结果* @param result* @return*/public  static  boolean isValidResult(double result){if (result<1){return  false;}return  result == Math.floor(result);}private static double getTwoNumCaculate(double num1, double num2, String operator) throws Exception {switch (operator) {case "+":return num1 + num2;case "-":return num1 - num2;case "*":return num1 * num2;case "/":return num1 / num2;default:throw new Exception("运算符不符合规范");}}
}

View Code

学有所得

  1. 是否学会了这种分析思路
  2. 是否这种需求分析思路可以运用在地方?
  3. 这种把每个原子需求编排成一个完整大需求,是否可以在他地方使用?

最后效果图:

转载于:https://www.cnblogs.com/lechengbo/p/10815016.html

任意1-10中的4个数字,使用加减乘除计算得出24结果的可能组合(java版),很多人小时候都玩过...相关推荐

  1. 实现简单计算器 两个数字的加减乘除计算

    C语言 输入要计算的表达式 得出结果 实现简单计算器 两个数字的加减乘除计算 // ASCII码表中加减乘除的顺序为 * + , - . / // 以乘号 * 为相对位置 然后根据其他符号与 * 的距 ...

  2. java中的repo什么意思_洛丽塔圈子常说的“repo”是什么意思?很多人都用错了

    [Lo意绵绵]独家原创.禁止一切搬运.抄袭.洗稿等行为. 相信平时喜欢逛洛丽塔服饰相关交流平台的女孩们,都会觉得"repo"这个词汇十分眼熟.每次收到新的小裙子时,大家都会忍不住与 ...

  3. c语言输入10个整数 求偶数个数6,任意输入10个整数,输出其中的偶数,和偶数的个数...

    任意输入10个整数,输出其中的偶数,和偶数的个数 一 . 运用java代码如下: package bean; import java.util.Scanner; public class b { pu ...

  4. vs中c语言wasd方向键需要按回车_二十多年前,根本没人用WASD玩游戏

    本文首发于微信公众号"BB姬"(bibiji300) B哥丨文 文章开始之前,我需要说明一点:现在的游戏基本都有自设按键的设定,所以这里说的WASD是一个普遍现象,而不代表所有人. ...

  5. 在python中输入10个整数并求出最大值_python练习题 :用户任意输入10个整数到列表中,然后由大到小排列并输出。...

    一:填空题: 1.python是一种面向_对象 __的高级语言. 2.python可以在多种平台运行,这体现了python的___可移植___特性. 3.python源代码被解释器转换后的格式为___ ...

  6. python语言的三种数字类型_Python语言中的类型之数字类型--Python(10)

    数据从不一样的角度能够用不一样的含义去解释它,如: 10,011,101 对上面这个数据,咱们有以下多种含义去解释它: 1)它是1个二进制数字,或者是1个十进制数字: 2)一段文本: 3)用 , 号分 ...

  7. ios手写_如何在iOS 10中发送手写和数字触摸消息

    ios手写 We live in a very high-tech world. We walk around with our heads bowed down to our phones tapp ...

  8. 组策略禁止自动锁定计算机,如何在Windows 10中禁用自动锁定

    原标题:如何在Windows 10中禁用自动锁定 Windows 10附带了许多功能,这样使工作更加轻松.其实有很多方法可以根据自己的喜好个性化使用.可以通过多种方式来个性化您的体验并控制计算机的行为 ...

  9. 游戏编程中的数学——随机数字生成(RNG)的黑暗秘密

    大家好,你们能听到我讲话吗?这个演讲的内容是介绍RNG(随机数字生成)的一些黑暗秘密.如你在大屏幕上看到的,Squirrel已经介绍了一些RNG的基础概念.首先,我想详细讲解几点.他的演讲更偏重理论, ...

最新文章

  1. OpenAI的GPT-3花费了1200万美元,现在放出商用API,人人皆可用
  2. 4G EPS 中的消息类型
  3. Unity UI代码自动生成
  4. 【Linux】一步一步学Linux——userdel命令(84)
  5. java map扩容机制_java中ConcurrentHashMap的扩容机制是怎样的?详细解析
  6. 当 Swagger 遇上 Torna,瞬间高大上了!
  7. nao机器人行走速度_数计学院学子在2020世界机器人大赛总决赛中荣获佳绩!
  8. Hibernate怎么提升数据库查询的性能 (1)
  9. java8 多行字符串_JDK8字符串拼接的正确姿势
  10. C#各种文件操作的代码与注释
  11. java在线反编译class文件工具地址
  12. 七夕王者服务器维护,七夕主题华裳上架、职业平衡来了!8月7日服务器例行维护公告...
  13. 硬盘显示无法访问由于IO设备错误的文件找到办法
  14. 如何让iframe背景色透明
  15. python爬取饿了么数据_爬取饿了么商铺信息
  16. Linux学习第一节课学习心得
  17. Confluence导出PDF文件乱码
  18. 通信协议晦涩难懂搞不定?看完这些动图恍然大悟
  19. LightOJ 1197 Help Hanzo
  20. 光猫修改上报服务器地址,怎样改光猫的ip地址!急求!!

热门文章

  1. Android 中文 API (27) —— SeekBar.OnSeekBarChangeListener
  2. 亿级流量电商详情页系统实战:缓存架构+高可用服务架构+微服务架构
  3. 6行代码实现ASP无组件上传
  4. 网页上加在线客服代码QQ,MSN,skype,goolge TALK,雅虎通,贸易通,淘宝旺旺
  5. 计算机常用端口一览表
  6. windows下文件共享以及通过网线在两台Windows电脑之间传数据
  7. docker 安装zookeeper集群
  8. 漫画:通俗易懂的进程与线程解释
  9. 预见未来 | 数据智能的现在与未来
  10. go标准命令详解0.1 go build