论坛首页 Java企业应用论坛

趣味编程:24点算法实现

浏览 37882 次
精华帖 (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 这样实在不高兴去区分的“同意”公式
0 请登录后投票
   发表时间:2009-01-12  
大家能不能说一下自己的算法 1-9 个数字组合【可以重复,因为扑克牌可以出现四个一样的数字】共可以得出多少种合法的组合
0 请登录后投票
   发表时间:2009-01-12  
大家能不能说一下自己的算法 1-9 个数字组合【可以重复,因为扑克牌可以出现四个一样的数字】共可以得出多少种合法的组合
0 请登录后投票
   发表时间: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种去处取一种
0 请登录后投票
   发表时间:2009-01-13  
呵呵,我上学的时候用vb写过这个。
0 请登录后投票
   发表时间: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




0 请登录后投票
   发表时间:2009-01-13  
楼上的,这个原来是扑克牌的算法,不能出现小数,每一步出来都是整数!
0 请登录后投票
   发表时间: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++) {
0 请登录后投票
   发表时间:2009-01-13  
什么意思,紧贴楼主的问题,不能超过10,否则,人脑就无法计算了,四重循环正确结论不一定是这个,因为中间还有很多无解的!
0 请登录后投票
   发表时间: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;
	}
}

0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics