任意1-10中的4个数字,使用加减乘除计算得出24结果的可能组合(java版),很多人小时候都玩过...
目錄
學(xué)有所得
需求
需求:任意1-10中的4個(gè)數(shù)字,使用加減乘除計(jì)算得出24結(jié)果的可能組合;
通過初步分析,我們可以得到如下規(guī)則:
規(guī)則:1、任意1-10中的4個(gè)數(shù)字;
2、使用加減乘除計(jì)算得出24;
3、在任何一次計(jì)算中不能出現(xiàn)小數(shù),
比如:(4.0 + 8.0) / (3.0 / 6.0) = 24.0,這種是不算的,雖然最終結(jié)果是24,因?yàn)?/6=0.5;(8.0 / 3.0) * (4.0 + 5.0) = 24.0,雖然最終為24,但是在第一步結(jié)果卻是小數(shù),所以不成立;代碼如下
4、整個(gè)運(yùn)算中應(yīng)該使用double類型,因?yàn)檎麛?shù)相除,使用int類型,在計(jì)算機(jī)中,會(huì)把余數(shù)抹掉,直接取整,這樣就會(huì)造成結(jié)果不正確;
那需求該如何分析呢,怎么劃分成小需求呢?
一般來說我們都會(huì)通過案例來分析,比如:這個(gè)需求,我們使用傳統(tǒng)的計(jì)算,假設(shè)我們已經(jīng)有這四個(gè)數(shù)[3,4,8,6],可能會(huì)有如下組合:
方案:((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;
我們暫時(shí)先分析這個(gè)幾個(gè)方案,大家看到這里,可以先思考一下有什么規(guī)律,有什么規(guī)則;
....................................................................................................Thinking..............................
從這些方案中,我們可以得出如下蹊蹺之處:
1、所有的方案中,都在這四個(gè)數(shù)的所有可能排列組合中(我記憶之中,應(yīng)該是高中數(shù)學(xué)的知識(shí)點(diǎn));
2、我們可以把計(jì)算法則歸納為兩種,所有的都可以歸納到一下兩種中去;
第一、從左到右的依次計(jì)算;
第二、兩兩組合,前兩個(gè)數(shù)計(jì)算結(jié)果和后兩個(gè)數(shù)的計(jì)算結(jié)果再次計(jì)算;
第三、每個(gè)方案都有3個(gè)運(yùn)算符;
不知道大家是不是和我發(fā)現(xiàn)的一樣不,或者說有更多的發(fā)現(xiàn);我認(rèn)為不管什么發(fā)現(xiàn)都可以先列出來,然后在逐個(gè)去去除一些太離譜的發(fā)現(xiàn);
我們?cè)倮^續(xù)順藤摸瓜,到此我們可以把需求分解如下:
我們繼續(xù)分析需求,看看是否可以再次分解
從上面的需求中我們可以進(jìn)一步進(jìn)行分解
第一、如何獲取四個(gè)數(shù)的所有排列組合?
1、舉例,我們繼續(xù)使用案列來分析,比如 [3,4,8,6]
[3,4,8,6](基準(zhǔn))
[4,3,8,6](第二和第一調(diào)換)
[3,8,4,6] [8,3,4,6](第三和第二調(diào)換,第二和第一調(diào)換)
[3,4,6,8] [3,6,4,8] [6,3,4,8] (第四和第三調(diào)換, 第三和第二調(diào)換,第二和第一調(diào)換)
這樣是不是所有的排列組合呢?顯然不是?因?yàn)檫€有三種基準(zhǔn)進(jìn)行上面的排列組合,也就是上面每行最后一列
[4,3,8,6](基準(zhǔn)2)
[8,3,4,6](基準(zhǔn)3)
[6,3,4,8](基準(zhǔn)4)
2、通過上面的舉例,我們就可以先獲取所有的基準(zhǔn)組合;
3、通過上面,我們可以知道每種基準(zhǔn)的所有組合;
4、通過上面的方法獲取的組合會(huì)有重復(fù),需要前需要去重;
這樣我們就能獲取4個(gè)數(shù)的所有排列組合;我感覺這種獲取所有排列組合的算法很笨重(有沒有感覺有點(diǎn)想冒泡排序),不優(yōu)雅,肯定有更優(yōu)的方案,只是我不知道而已,如果知道的可以留言,謝謝;
所有排列分析到此,是不是還需要繼續(xù)分析,可以繼續(xù)思考;本人感覺可以落地了;如果覺得需要繼續(xù)分析的,可以繼續(xù)分解,知道自己很清晰,知道怎么干為止(這個(gè)因人而異);請(qǐng)看代碼;
獲取所有基準(zhǔn)代碼:
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獲取每個(gè)基準(zhǔn)的所有排列組合:
/*** 獲取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下標(biāo)遇到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第二,對(duì)于算法法則該如何繼續(xù)分析呢?我們可以繼續(xù)使用舉例
從上面隨意獲取一種排列組合,比如:[3,4,8,6]
1、從左到右的組合,在上面四個(gè)數(shù)字中,任意兩個(gè)數(shù)中,我們可以有+,- ,*,/這四種算法,這又是一種計(jì)算的所有排列組合,并把結(jié)果和24對(duì)比,如果相等,那就是可行方案;
那我們是不是繼續(xù)使用上面獲取組合的方式呢?顯然不是,這里關(guān)鍵點(diǎn)在于:任意兩個(gè)數(shù)中都有+-*/的算法,這里我們可以使用三個(gè)for循環(huán)解決;
舉例:((3.0 * 4.0) - 8.0) * 6.0=24.0;
?
2、兩兩組合,思路和上面有些相似,
前兩個(gè)數(shù)的任意計(jì)算結(jié)果1,
后兩個(gè)數(shù)的任意計(jì)算結(jié)果2,
結(jié)果1和結(jié)果2的任意計(jì)算結(jié)果3,
結(jié)果3和24對(duì)比,如果相等,那就是可行方案;
舉例:(3.0 * 4.0) * (8.0 - 6.0) = 24.0;
?
?
某一種四個(gè)數(shù)的所有運(yùn)算排列通過上面的方式我們可以全部獲取,分析到此,我覺得代碼可以落地,當(dāng)然,如果你覺得還不夠清晰,可以繼續(xù)分析,直到自己清晰為止,這里我只是提供分解需求的思路而已;在軟件工程中,我們必定先分析需求,然后分解需求,我們有四色分析方式,我們還有DDD領(lǐng)域的分析方式等,都是需要通過逐步分解成更小的需求來反復(fù)驗(yàn)證的;
?
到目前為止我們可以得出如下思維導(dǎo)圖
?
把各種子孫需求,通過組合編排,最終成為一個(gè)完整的大需求解決方案
最后,我們把每個(gè)小的需求加上一些規(guī)則邏輯組合成完整的大需求,我們暫時(shí)叫做編排吧;
這里其實(shí)也是一個(gè)難點(diǎn),很多人希望一次性把代碼寫完整,寫正確,其實(shí)這種思路是不正確的,這樣只會(huì)增加代碼的難度,一次性能把代碼寫的有多完整多正確,這個(gè)跟每個(gè)人的編程經(jīng)驗(yàn)熟練度有關(guān);
不管編程多牛,從無到有的敲代碼方向不是一次性把左右的代碼完成,重點(diǎn)方向把核心邏輯思路編寫上,其次才逐步把一些細(xì)節(jié)邏輯規(guī)則加上去,這個(gè)就和我們小時(shí)候?qū)W畫畫一樣,畫一顆樹先畫主干然后畫葉子最后添加果子和花之類的;
?
到目前為止是否完整呢?其實(shí)還差一點(diǎn),任意的1-10的數(shù)字從哪里獲取,不過需求沒有明確,可以是用戶輸入,數(shù)據(jù)庫(kù)獲取,其他接口的傳入,我們這里就定位用戶輸入吧
獲取用戶輸入代碼如下:
double[] array = new double[4];int index=0;Scanner scanner=new Scanner(System.in);while (index<4){System.out.println(String.format("請(qǐng)輸入第%s個(gè)1-10的整數(shù)",index+1));String tempNumStr=scanner.nextLine();if(!StringUtils.isNumeric(tempNumStr)){System.out.println("你輸入的不是一個(gè)整數(shù)");continue;}double tmpNum=Double.valueOf(tempNumStr);if (tmpNum<0 || tmpNum>10){System.out.println("你輸入的數(shù)字不是1-10的數(shù)字");continue;}array[index++]=tmpNum;}System.out.println(String.format("你輸入的4個(gè)1-10的整數(shù)為%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 {/*** 計(jì)算24點(diǎn)中可以到的操作*/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("請(qǐng)輸入第%s個(gè)1-10的整數(shù)",index+1));String tempNumStr=scanner.nextLine();if(!StringUtils.isNumeric(tempNumStr)){System.out.println("你輸入的不是一個(gè)整數(shù)");continue;}double tmpNum=Double.valueOf(tempNumStr);if (tmpNum<0 || tmpNum>10){System.out.println("你輸入的數(shù)字不是1-10的數(shù)字");continue;}array[index++]=tmpNum;}System.out.println(String.format("你輸入的4個(gè)1-10的整數(shù)為%s,%s,%s,%s",array[0],array[1],array[2],array[3]));System.out.println("結(jié)果如下:");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("總共方案數(shù)量:" + 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下標(biāo)遇到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;}/*** 計(jì)算array能算24點(diǎn)的所有組合,從左到右的順序** @param* @throws Exception*/public static int caculate24Point(double[] array) throws Exception {int count = 0;if (array.length != 4) {throw new Exception("不是四個(gè)數(shù)");}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;}/*** 計(jì)算array能算24點(diǎn)的所有組合 ,兩兩組合** @param array* @return* @throws Exception*/public static int caculate24Point2(double[] array) throws Exception {int count = 0;if (array.length != 4) {throw new Exception("不是四個(gè)數(shù)");}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;}/*** 是否為合法的計(jì)算結(jié)果* @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("運(yùn)算符不符合規(guī)范");}} } View Code?
?
學(xué)有所得
最后效果圖:
?
轉(zhuǎn)載于:https://www.cnblogs.com/lechengbo/p/10815016.html
總結(jié)
以上是生活随笔為你收集整理的任意1-10中的4个数字,使用加减乘除计算得出24结果的可能组合(java版),很多人小时候都玩过...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。