锁定老帖子 主题:趣味编程:24点算法实现
精华帖 (0) :: 良好帖 (2) :: 新手帖 (2) :: 隐藏帖 (1)
|
|
---|---|
作者 | 正文 |
发表时间:2009-01-12
我5年前写过一个算法,24点的,出现的重复很少。
提示: +,*,是没有逆运算的 -,虽然有逆运算,但是可以不用考虑的 / 有逆运算,例如 (5-1/5)*5 给每个符号设定优先级,1、2、3,另外我的算法里面还考虑到了 ^, log, √(根号)(还有些奇奇怪怪的符号,不好意思说) / 1 没有意义,因为 /1 = *1 有逆运算的符号其实就是做为第二个参数,如果后者符号也可逆运算,就要加括号,例如:1/5/2 和 1/(5/2)是不一样的 基本上现在跑出来的程序结果令人满意,只会出现一些类似: 9 * 8 / 3 = 24 和 9 / (3 / = 24 这样实在不高兴去区分的“同意”公式 |
|
返回顶楼 | |
发表时间:2009-01-12
大家能不能说一下自己的算法 1-9 个数字组合【可以重复,因为扑克牌可以出现四个一样的数字】共可以得出多少种合法的组合
|
|
返回顶楼 | |
发表时间:2009-01-12
大家能不能说一下自己的算法 1-9 个数字组合【可以重复,因为扑克牌可以出现四个一样的数字】共可以得出多少种合法的组合
|
|
返回顶楼 | |
发表时间:2009-01-13
C4取2 * c4取1 * c3取2 * c4取1 *c2取2 * c4取1
----------------------------- 1. 4个数取2 4种运算取一种 2. 把得数放回原数据中 3. 3个数取2 4种运算取一种 4. 把得数放回原数据中 5. 2个数取2 4种去处取一种 |
|
返回顶楼 | |
发表时间:2009-01-13
呵呵,我上学的时候用vb写过这个。
|
|
返回顶楼 | |
发表时间:2009-01-13
最后修改:2009-01-13
qdzheng 写道 if (op(op[p],op(op[o],v[idx[0]],v[idx[1]]),op(op[t],v[idx[2]],v[idx[3]]))==24) 为什么是“整数”24?! 这样对于1 5 5 5 正解(5-1/5)×5==24你的代码就算不出来了。 应该取浮点数,同时考虑浮点误差吧? 恰好我刚出来混时也写过一个(原帖在infoxa: http://www.infoxa.com/asp/article_file/xxnr_article_1102.htm 那时的代码写的一看就是newbie的风格,可以重构一下): /* * Created on 2005-10-18 * * TODO To change the template for this generated file go to * Window - Preferences - Java - Code Style - Code Templates */ package com.netengine.test; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * @author cds * * TODO To change the template for this generated type comment go to * Window - Preferences - Java - Code Style - Code Templates */ public class Calculator { //用来保存所有的计算结果: private List allResults = new ArrayList(); //操作符代码 :仅限四则运算 private int operator1,operator2,operator3; public int getOperator1() { return this.operator1; } public void setOperator1(int operator1) { this.operator1 = operator1; } public int getOperator2() { return this.operator2; } public void setOperator2(int operator2) { this.operator2 = operator2; } public int getOperator3() { return this.operator3; } public void setOperator3(int operator3) { this.operator3 = operator3; } //输入的4个数字: private float[] inputedNumbers = new float[4]; //算法需要把输入的4个数字按一定规则排序: private float[] sortedNumbers = new float[4]; //排序算法所需要的下标数组: private int[][] indexs = { {0,1,2,3}, {0,1,3,2}, {0,2,1,3}, {0,2,3,1}, {0,3,1,2}, {0,3,2,1}, {1,0,2,3}, {1,0,3,2}, {1,2,0,3}, {1,2,3,0}, {1,3,0,2}, {1,3,2,0}, {2,0,1,3}, {2,0,3,1}, {2,1,0,3}, {2,1,3,0}, {2,3,0,1}, {2,3,1,0}, {3,0,1,2}, {3,0,2,1}, {3,1,0,2}, {3,1,2,0}, {3,2,0,1}, {3,2,1,0} }; //表示是第几回合(一共要经过24回合) private int round = 0; public int getRound() { return this.round; } public void setRound(int round) { this.round = round; } //本算法中最重要的数据结构,模拟二叉树,result[0]是根结点, //如果得到result[0]的值为24,就算出来了 private float result[] = new float[9]; private void print(String s){ System.out.println(s); } //提取输入的4个数字,存入数组inputedNumbers private boolean setNumbers(String[] str){ if(str.length != 4){ print("Please input 4 Integers!"); return false; } try{ inputedNumbers[0] = Integer.parseInt(str[0]); inputedNumbers[1] = Integer.parseInt(str[1]); inputedNumbers[2] = Integer.parseInt(str[2]); inputedNumbers[3] = Integer.parseInt(str[3]); }catch(Exception ex){ print("Please input 4 Integers!"); return false; } return true; } //给二叉树中指定结点赋值: private void setResult(int index,float value){ result[index] = value; } //得到二叉树中指定结点的值: private float getResult(int index){ return result[index]; } //生成算式: private String generateNumSentence(int intOptr,float opnd1,float opnd2,float rst){ String ret = ""; switch(intOptr){ case 0: ret = opnd1 + "+" + opnd2 + "=" + rst; //原先存在一个隐藏的bug:把rst写成了result,与类Calculator的域result冲突。 break; case 1: ret = opnd1 + "-" + opnd2 + "=" + rst; break; case 2: ret = opnd2 + "-" + opnd1 + "=" + rst; break; case 3: ret = opnd1 + "*" + opnd2 + "=" + rst; break; case 4: ret = opnd1 + "/" + opnd2 + "=" + rst; break; case 5: ret = opnd2 + "/" + opnd1 + "=" + rst; break; } return ret; } //打印计算出的结果: private void printResult(){ /** TODO*/ int count = 0; int howManyAnswers = this.allResults.size(); if(howManyAnswers > 0){ print("一共有" + howManyAnswers + "种计算方法"); for(Iterator i = this.allResults.iterator();i.hasNext();){ print("第" + (++count) + "个:\n" + i.next()); } } else{ print("无解!"); } } //排序方法: private void sortNumbers(int rnd){ if(rnd < 0 || rnd > 23){ print("Error!"); return; } sortedNumbers[0] = inputedNumbers[indexs[rnd][0]]; sortedNumbers[1] = inputedNumbers[indexs[rnd][1]]; sortedNumbers[2] = inputedNumbers[indexs[rnd][2]]; sortedNumbers[3] = inputedNumbers[indexs[rnd][3]]; } //根据运算符代码、2个操作数,得到中间结果: private float getMidValue(int i,float m,float n){ float ret = 0f; switch(i){ case 0: ret = m + n; break; case 1: ret = m - n; break; case 2: ret = n - m; break; case 3: ret = m * n; break; case 4: try{ ret = m / n; }catch(Exception ex1){ ret = Float.MAX_VALUE; } break; case 5: try{ ret = n / m; }catch(Exception ex2){ ret = Float.MAX_VALUE; } break; } return ret; } //因为有两种结构的二叉树,计算24的算法也有两种: private void calculate(){ setResult(3,sortedNumbers[0]); setResult(4,sortedNumbers[1]); setResult(5,sortedNumbers[2]); setResult(6,sortedNumbers[3]); for(int i = 0;i < 6;i++){ setResult(1,getMidValue(i,getResult(3),getResult(4))); for(int j = 0;j < 6;j++){ setResult(2,getMidValue(j,getResult(5),getResult(6))); for(int k = 0;k < 6;k++){ setResult(0,getMidValue(k,getResult(1),getResult(2))); if(Math.abs(getResult(0) - 24) < 0.001){ this.setOperator1(i); this.setOperator2(j); this.setOperator3(k); //把计算24的算式保存到List中 saveResult(1); } if(i == 5 && j == 5 && k == 5){ calculate_1(); } } } } } /** * */ private void saveResult(int type) { // TODO Auto-generated method stub String ns = null; switch(type){ case 1: ns = "Step1:"+this.generateNumSentence(this.getOperator1(),this.getResult(3),this.getResult(4),this.getResult(1)) + "\n"; ns += "Step2:"+this.generateNumSentence(this.getOperator2(),this.getResult(5),this.getResult(6),this.getResult(2)) + "\n"; ns += "Step3:"+this.generateNumSentence(this.getOperator3(),this.getResult(1),this.getResult(2),this.getResult(0)) + "\n"; break; case 2: ns = "Step1:"+this.generateNumSentence(this.getOperator1(),this.getResult(7),this.getResult(8),this.getResult(3)) + "\n"; ns += "Step2:"+this.generateNumSentence(this.getOperator2(),this.getResult(3),this.getResult(4),this.getResult(1)) + "\n"; ns += "Step3:"+this.generateNumSentence(this.getOperator3(),this.getResult(1),this.getResult(2),this.getResult(0)) + "\n"; break; } boolean dup = false; for(Iterator i = this.allResults.iterator(); i.hasNext();){ if(ns.equals((String)i.next())){ dup = true; break; } } if(!dup){this.allResults.add(ns);} } //第2种后备算法: private void calculate_1(){ setResult(7,sortedNumbers[0]); setResult(8,sortedNumbers[1]); setResult(4,sortedNumbers[2]); setResult(2,sortedNumbers[3]); for(int i = 0;i < 6;i++){ setResult(3,getMidValue(i,getResult(7),getResult(8))); for(int j = 0;j < 6;j++){ setResult(1,getMidValue(j,getResult(3),getResult(4))); for(int k = 0;k < 6;k++){ setResult(0,getMidValue(k,getResult(1),getResult(2))); if(Math.abs(getResult(0) - 24) < 0.001){ this.setOperator1(i); this.setOperator2(j); this.setOperator3(k); //把计算24的算式保存到List中 saveResult(2); }else if(i == 5 && j == 5 && k == 5){ // print("No solution at round "+(this.getRound()+1)+"!"); } } } } } public static void main(String[] args){ Calculator cal = new Calculator(); if(!cal.setNumbers(args)){return;} for(int i = 0; i < 24; i++){ cal.setRound(i); cal.sortNumbers(i); cal.calculate(); // cal.printResult(); } cal.printResult(); } } ==================================== 如果输入四个值 1 5 5 5 将只打印一个结果如下: 一共有1种计算方法 第1个: Step1:1.0/5.0=0.2 Step2:5.0-0.2=4.8 Step3:4.8*5.0=24.0 |
|
返回顶楼 | |
发表时间:2009-01-13
楼上的,这个原来是扑克牌的算法,不能出现小数,每一步出来都是整数!
|
|
返回顶楼 | |
发表时间:2009-01-13
kjj 写道 大家能不能说一下自己的算法 1-9 个数字组合【可以重复,因为扑克牌可以出现四个一样的数字】共可以得出多少种合法的组合
for (int i = 1; i <= 13; i++) { for (int j = i; j <= 13; j++) { for (int k = j; k <= 13; k++) { for (int l = k; l <= 13; l++) { |
|
返回顶楼 | |
发表时间:2009-01-13
什么意思,紧贴楼主的问题,不能超过10,否则,人脑就无法计算了,四重循环正确结论不一定是这个,因为中间还有很多无解的!
|
|
返回顶楼 | |
发表时间:2009-01-13
本方法,等手上任务完成再优化
package com; public class My24 { /** * @param args */ public static void main(String[] args) { if(args.length != 1){ System.out.println("需要一个四位整数型参数,不包含0"); System.exit(-1); } int num = Integer.valueOf(args[0]); if(num >= 9999 || num <= 1117){ System.out.println("数字超出范围"); System.exit(-1); } for(int i = 10; i < 10000; i *= 10){ if(num % i <= i / 10){ System.out.println("数字不能包含0"); System.exit(-1); } } My24 my24 = new My24(num); my24.js(0, "begin: "); } private int[][] nums = {{0, 0, 0, 0}, {0, 0, 0, 0}}; /** * 把四位数字放到数组nums中 * @param num */ public My24(int num){ for(int i = 0; i < 4; i++){ nums[0][i] = num % 10; num = num / 10; System.out.print(nums[0][i] + " "); } } public int js(int v, String stra){ int result = v; int num = 0; String strb = stra; strb += " = " + v; for(int i = 0; i < 4; i++){ if(nums[1][i] == 0){ num = nums[0][i]; nums[1][i] = 1; //进入运算 if(v == 0){ result = js(num, strb + (" + " + num)); }else{ result = js(v + num, strb + (" + " + num)); result = js(v - num, strb + (" - " + num)); result = js(v * num, strb + (" * " + num)); result = js(v / num, strb + (" / " + num)); } nums[1][i] = 0; } } if(num == 0){ //四个数字都被用了 if(result == 24 || result == -24){ //打印出过程 System.out.println(stra); } } return v; } } |
|
返回顶楼 | |