我的24点算法,希望大家执正

topglory 2004-04-12 06:05:57
前边一个朋友要最优算法,我不敢现眼,后来又有朋友问我要24点的算法,我所性就贴出来,大家批判批判。指正者有分。

用了三个类
Get24.java
Combination.java
Prompt.java

//Get24.java
public class Get24
{
static String getOperator(int i){
switch(i){
case 0:
return "+";
case 1:
return "-";
case 2:
return "*";
default:
return "/";
}
}
static float cacu(float a,float b,int o){
switch(o){
case 0:
return a+b;
case 1:
return a-b;
case 2:
return a*b;
default:
return a/b;
}
}
static int getInt(String s){
int i=0;
try{
i=Integer.parseInt(s);
if(i<=0)
throw new NumberFormatException();
}catch(NumberFormatException nfe){
return getInt(Prompt.read("输入错误,重新输入: "));
}
return i;
}
static boolean equal(float a,float b){
if(Math.abs(a-b)<0.01f)
return true;
return false;
}
static int caculate(int[] arr,int x,int y,int z){
float a=(float)arr[0];
float b=(float)arr[1];
float c=(float)arr[2];
float d=(float)arr[3];
if(equal(cacu(cacu(cacu(a,b,x),c,y),d,z),24.0f))
return 1;
if(equal(cacu(cacu(a,b,x),cacu(c,d,z),y),24.0f))
return 2;
if(equal(cacu(cacu(a,cacu(b,c,y),x),d,z),24.0f))
return 3;
if(equal(cacu(a,cacu(cacu(b,c,y),d,z),x),24.0f))
return 4;
if(equal(cacu(a,cacu(b,cacu(c,d,z),y),x),24.0f))
return 5;
return -1;
}
static boolean cacu24(int[][] a){
int flag;
int[] op={0,1,2,3};
for(int i=0;i<a.length;i++){
for(int x=0;x<op.length;x++){
for(int y=0;y<op.length;y++){
for(int z=0;z<op.length;z++){
if((flag=caculate(a[i],x,y,z))>0){
printFormula(a[i],x,y,z,flag);
return true;
}
}
}
}
}
return false;
}
static void printFormula(int[] a,int x,int y,int z,int flag){
int xx=x>1?1:0;
int yy=y>1?1:0;
int zz=z>1?1:0;
StringBuffer sb=new StringBuffer();
if(flag==1){
if(yy>xx)
sb.append("(");
if(zz>xx||zz>yy)
sb.append("(");
sb.append(a[0]);
sb.append(getOperator(x));
sb.append(a[1]);
if(yy>xx)
sb.append(")");
sb.append(getOperator(y));
sb.append(a[2]);
if(zz>xx||zz>yy)
sb.append(")");
sb.append(getOperator(z));
sb.append(a[3]);
}
else if(flag==2){
if(yy>xx)
sb.append("(");
sb.append(a[0]);
sb.append(getOperator(x));
sb.append(a[1]);
if(yy>xx)
sb.append(")");
sb.append(getOperator(y));
if(yy>zz)
sb.append("(");
else if(yy==zz){
if((z==y&&y!=0&&y!=3)||(z!=y&&y!=0&&y!=2))
sb.append("(");
}
sb.append(a[2]);
sb.append(getOperator(z));
sb.append(a[3]);
if(yy>zz)
sb.append(")");
else if(yy==zz){
if((z==y&&y!=0&&y!=3)||(z!=y&&y!=0&&y!=2))
sb.append(")");
}
}
else if(flag==3){
if(zz>xx||zz>yy)
sb.append("(");
sb.append(a[0]);
sb.append(getOperator(x));
if(yy<xx)
sb.append("(");
else if(yy==xx){
if((x==y&&y!=0&&y!=3)||(x!=y&&x!=0&&x!=2))
sb.append("(");
}
sb.append(a[1]);
sb.append(getOperator(y));
sb.append(a[2]);
if(yy<xx)
sb.append(")");
else if(yy==xx){
if((x==y&&y!=0&&y!=3)||(x!=y&&x!=0&&x!=2))
sb.append(")");
}
if(zz>yy||zz>xx)
sb.append(")");
sb.append(getOperator(z));
sb.append(a[3]);
}
else if(flag==4){
sb.append(a[0]);
sb.append(getOperator(x));
if(xx>zz||xx>yy||x==1||x==3)
sb.append("(");
if(zz>yy)
sb.append("(");
sb.append(a[1]);
sb.append(getOperator(y));
sb.append(a[2]);
if(zz>yy)
sb.append(")");
sb.append(getOperator(z));
sb.append(a[3]);
if(xx>zz||xx>yy||x==1||x==3)
sb.append(")");
}
else if(flag==5){
sb.append(a[0]);
sb.append(getOperator(x));
if(xx>zz||xx>yy||x==1||x==3)
sb.append("(");
sb.append(a[1]);
sb.append(getOperator(y));
if(yy>zz||(yy==zz&&y!=0&&y!=2))
sb.append("(");
sb.append(a[2]);
sb.append(getOperator(z));
sb.append(a[3]);
if(xx>zz||xx>yy||x==1||x==3)
sb.append(")");
if(yy>zz||(yy==zz&&y!=0&&y!=2))
sb.append(")");
}
sb.append("=24");
System.out.println(sb);
}
public static void main(String[] args){
int numbers[]=new int[4];
System.out.println("请输入4个大于0的正整数");
for(int i=0;i<numbers.length;i++)
numbers[i]=getInt(Prompt.read("第 "+(i+1)+" 个整数为 :"));


int[][] a=Combination.getCombination(numbers);
System.out.println("====================================");
if(!cacu24(a))
System.out.println("无法用四则运算得到24。");
}
};
...全文
150 35 打赏 收藏 转发到动态 举报
写回复
用AI写文章
35 条回复
切换为时间正序
请发表友善的回复…
发表回复
wolfsquare 2004-04-14
  • 打赏
  • 举报
回复
同意楼上第一点.
还可以定义一个顺序运算符,当遇到顺序运算符时就将该操作数放到最后运算来解决这个括号优先问题.
Schlemiel 2004-04-14
  • 打赏
  • 举报
回复
第一,没必要去掉相似解,因为算24点的规则是尽快得到一个答案,并不要求得出所有答案,所以只要有一个答案符合要求就可以结束。

第二,加括号的问题非常简单。实际上,括号的组合也只有7种情况(包括无括号的情况),再加一层穷举循环就行了。我们用@代表任意运算符:
a@b@c@d
(a@b)@c@d
a@(b@c)@d
a@b@(c@d)
(a@b)@(c@d)
(a@b@c)@d
a@(b@c@d)
eshow 2004-04-14
  • 打赏
  • 举报
回复
我觉得这踢的难点还不在于穷举,而在于将穷举所得的结果如何判断加括号,以及如何去掉相似解。比如(3+1)*(5+1),(5+1)*(3+1),(1+3)*(1+5),(1+3)*(5+1)等都是相似解,穷举会一股脑都给你,如何给出一组判断相似解的规则以及如何实现才是真正的难点。
wolfsquare 2004-04-14
  • 打赏
  • 举报
回复
我的算法的确有问题. 顺序法的四个数在第一步运算后没有再次做四则运算的组合运算.
不过真要这样做的话算法似乎又过于复杂了,看来还要重新考虑考虑.
eshow 2004-04-14
  • 打赏
  • 举报
回复
TO:Schlemiel(维特根斯坦的扇子)
第一,那每个人对程序的要求不一样,如果只要一个解就行,那当然不存在问题;

第二,括号也穷举,那你就要解决字符串转化表达式的问题,“(a@b@c)@d”的字串程序如何认得来计算?所以这同样也是一个难点。坛子里不是很多人都问怎么把字串变成表达式的吗?
shhgs 2004-04-13
  • 打赏
  • 举报
回复
To: 楼主

基本上还是手工穷举所有的组合。要是给你5个,6个,甚至更多的数字,你的程序,或者说这个算法大概就报废了吧。

我在csdn上发表过24点算法分析的文章,用Python实现的,你可以看看。

To: Schlemiel(维特根斯坦的扇子)

别吹牛,我用Python写过,150多行。

20行,你写一个,给我开开眼。
Schlemiel 2004-04-13
  • 打赏
  • 举报
回复
有够费劲。要是用Python或者Ruby,顶多20行就搞定,非要用Java来费这个劲。
xsp 2004-04-13
  • 打赏
  • 举报
回复
注释太少,阅读困难。
flyforlove 2004-04-13
  • 打赏
  • 举报
回复
我不知道24点的规则是不是可以在中间产生小数。
flyforlove 2004-04-13
  • 打赏
  • 举报
回复
输入3,3,8,8
得到的结果

8/(3-8/3)=24
topglory 2004-04-13
  • 打赏
  • 举报
回复
怎么没人指正,我就自己指正一下子

在printFormula函数中

if(flag==3){}是多余的
shhgs 2004-04-13
  • 打赏
  • 举报
回复
To: wolfsquare(狼平方 Swing报表工人)
肯定要有括号。给你一个组合, (3, 1, 5, 1) 如果不加括号,就是无解,但是一眼就能看出(3+1)*(5+1)

Python的代码比Java的少,不是说说的,你可以到文档区去看。而且我的程序,并不仅限于用4个数算24,从理论上讲它能用任意多的数算24。

To: Schlemiel(维特根斯坦的扇子)
最后那个还差不多。50~60行吧。
eshow 2004-04-13
  • 打赏
  • 举报
回复
package Cal_24;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import java.awt.*;
import java.awt.event.*;
import com.bruceeckel.swing.*;
import java.util.*;
//这个就是前台窗口的显示了!不过import了Thinking in Java 2nd中BruceEckel写的一个
//将Applet当作Application运行的方法。其实不用Applet直接用Application实现就可以了。
//早期的联系,还不太理解Applet和Application,所以。。。呵呵,见笑。
public class Cal_24 extends JApplet {
JLabel jl1=new JLabel("Please Input 4 Source Numbers (1-13):"),
jl2=new JLabel("Show Result:");
JButton b=new JButton("Calculate");
JTextField[] t=new JTextField[4];
JTextArea ta=new JTextArea(10,15);
JScrollPane sp=new JScrollPane(ta,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

class BL implements ActionListener {
public void actionPerformed(ActionEvent e) {
String[] str=new String[4];
boolean legalNum=true;
Collection al= new ArrayList();
for(int i=1;i<=13;i++)
al.add(Integer.toString(i));
for(int i=0;i<t.length;i++) {
str[i]=t[i].getText();
if(!al.contains(str[i])) {
legalNum=false;
break;
}
int j=Integer.parseInt(str[i]);
/*if (j>13||j<1) {
legalNum=false;
break;}*/
}
if(legalNum) {
Cal24 cal24 = new Cal24(str);
HashSet s = cal24.work();
if(cal24.success()) {
ta.setText("Calculation succeed!\n");
Output o = new Output();
o.resultTree(s);
s=o.getResult();
Iterator it = s.iterator();
while(it.hasNext())
ta.append((String)it.next()+"=24\n");
} else {
ta.setText("Calculation failed!\n");
}
} else {
JOptionPane.showMessageDialog(Cal_24.this,"Illegal Input!","Warning!",
JOptionPane.WARNING_MESSAGE);
}
}
}

public void init() {
Container cp = getContentPane();
cp.setLayout(new FlowLayout());
for(int i=0;i<t.length;i++)
t[i]=new JTextField(2);
b.addActionListener(new BL());
cp.add(jl1);
for(int i=0;i<t.length;i++)
cp.add(t[i]);
cp.add(b);
cp.add(jl2);
ta.setEditable(false);
cp.add(sp);
}

public static void main(String[] args) {
Console.run(new Cal_24(),260,350);
}
}
eshow 2004-04-13
  • 打赏
  • 举报
回复
package Cal_24;
import java.util.*;
//下面这一段是解析上面生成的每一个合法结果,在合理的位置加上括号,并运用交换率去掉
//一些明显的相似解。
class BinNode {
private String opx;
private BinNode left;
private BinNode right;

public BinNode() {}
public BinNode(String op) {
opx = op; left = null; right = null; }

public BinNode(String op, BinNode l, BinNode r) {
opx=op; left = l; right = r; }

public BinNode(String op, String l, String r) {
opx = op;
left = new BinNode(l);
right = new BinNode(r);
}

public String element() { return opx;}
public String setElement(String v) {return opx = v;}
public BinNode left() { return left;}
public BinNode setLeft(BinNode p) {return left = p;}
public BinNode setLeft(String v) {return left = new BinNode(v);}
public BinNode right() {return right;}
public BinNode setRight(BinNode p) { return right = p; }
public BinNode setRight(String v) { return right = new BinNode(v);}
public boolean isLeaf() { return (left==null&&right==null);}

public boolean equals(Object o) {
boolean b=false;
if(o instanceof BinNode) {
BinNode t=(BinNode)o;
if(t.element()==element()) {
if(t.isLeaf()&&this.isLeaf()) b=true;
else {
b=t.left().equals(this.left())&&t.right().equals(this.right());
if(!b&&(element()=="+"||element()=="*"))
b=t.left().equals(this.right())&&t.right().equals(this.left());
}
}

}
return b;
}

public int hashCode() {
return 1;
}

}


class CTree {
private static BinNode createNode(String i, BinNode l, BinNode r) {
BinNode bn = new BinNode();
switch (Integer.parseInt(i)) {
case(0): bn=new BinNode("+",l,r); break;
case(1): bn=new BinNode("-",l,r); break;
case(2): bn=new BinNode("*",l,r); break;
case(3): bn=new BinNode("/",l,r); break;
case(4): bn=new BinNode("-",r,l); break;
case(5): bn=new BinNode("/",r,l); break;
default: bn=null;
}
return bn;
}

public static BinNode createTree(String[] a, int i) {
BinNode bn = new BinNode();
if(a[a.length-1]=="A") {
if(i==0) return new BinNode(a[i]);
else {
BinNode ln = new BinNode(a[i]);
bn=createNode(a[i-1],createTree(a,i-2),ln);
}
}
if(a[a.length-1]=="B") {
BinNode left = createNode(a[1],new BinNode(a[0]),new BinNode(a[2]));
BinNode right = createNode(a[5],new BinNode(a[4]),new BinNode(a[6]));
bn=createNode(a[3],left,right);
}
return bn;
}

private static BinNode addParenth(BinNode b) {
BinNode b1 = b;
while(!b.isLeaf()) b=b.left();
b.setElement("("+b.element());
b=b1;
while(!b.isLeaf()) b=b.right();
b.setElement(b.element()+")");
b=b1;
return b;
}


public static BinNode modifyTree(BinNode bn) {
if(!bn.left().isLeaf()&&!bn.right().isLeaf()) {
switch(bn.element().charAt(0)) {
case('+'): break;
case('-'):
if(bn.right().element()=="+"||bn.right().element()=="-")
bn.setRight(addParenth(bn.right()));
break;
case('*'):
if(bn.left().element()=="+"||bn.left().element()=="-")
bn.setLeft(addParenth(bn.left()));
if(bn.right().element()=="+"||bn.right().element()=="-")
bn.setRight(addParenth(bn.right()));
break;
case('/'):
if(bn.left().element()=="+"||bn.left().element()=="-")
bn.setLeft(addParenth(bn.left()));
bn.setRight(addParenth(bn.right()));
break;
default:break;
}
return bn;
}
else{

if((bn.left()==null||bn.left().isLeaf()) && (bn.right()==null||bn.right().isLeaf())) return bn;
else {
if (bn.element()=="/") {
if(!bn.left().isLeaf()&&(bn.left().element()=="+"||bn.left().element()=="-"))
bn.setLeft(addParenth(bn.left()));
if(!bn.right().isLeaf())
bn.setRight(addParenth(bn.right()));
} else if(bn.element()=="*") {
if(!bn.left().isLeaf()&&(bn.left().element()=="+"||bn.left().element()=="-"))
bn.setLeft(addParenth(bn.left()));
if(!bn.right().isLeaf()&&(bn.right().element()=="+"||bn.right().element()=="-"))
bn.setRight(addParenth(bn.right()));
}
else if(bn.element()=="-"&&bn.left().isLeaf()) {
if(bn.right().element()=="+"||bn.right().element()=="-")
bn.setRight(addParenth(bn.right()));
}
if(!bn.left().isLeaf()) bn.setLeft(modifyTree(bn.left()));
if(!bn.right().isLeaf()) bn.setRight(modifyTree(bn.right()));
return bn;
}
}

}
}

class Output {
private HashSet rs = new HashSet();

public String traverse(BinNode rt) {
String s=new String();
if(rt==null) return s;

s+=traverse(rt.left());
s+=rt.element();
s+=traverse(rt.right());
return s;
}

public void resultTree(HashSet s) {
HashSet hs = new HashSet();
Iterator it = s.iterator();
while(it.hasNext()) {
String[] c = (String[])it.next();
//for(int i=0;i<c.length;i++)
//System.out.println(c[i]);
BinNode mbn=CTree.createTree(c,c.length-2);
hs.add(mbn);
}
Iterator hsit = hs.iterator();
while(hsit.hasNext()) {
BinNode bnt=(BinNode)hsit.next();
BinNode rbn=CTree.modifyTree(bnt);
rs.add(traverse(rbn));
//System.out.println(traverse(rbn));
}
//return rs;
}

public void prtResult() {
Iterator it = rs.iterator();
while(it.hasNext())
System.out.println((String)it.next()+"=24");
}

public HashSet getResult() {return rs;}
}

eshow 2004-04-13
  • 打赏
  • 举报
回复
呵呵,我也写了一个,还能去掉一些相似解。例如乘法,加法的交换律1+2和2+1只显示一个,下面是我的。早期的练习,也许OO思想体现得不太好,但是对HashSet和树的运用还是不错的。

package Cal_24;
import java.util.*;

//这个类是进行穷举计算生成结果集的
public class Cal24 {
private Set sourceSet = new HashSet();
private boolean success = false;

Cal24(String[] s) {
sourceSet=new input().rearrange(new MyArray(s));
}

private double calValue(double op1, double op2, int operator)
{
switch(operator) {
case 0 : return op1 + op2;
case 1 : return op1 - op2;
case 2 : return op1 * op2;
case 3 : return op1 / op2;
case 4 : return op2 - op1;
case 5 : return op2 / op1;
default: System.out.println("Error!");
return 0;
}
}

public HashSet work(MyArray a) {
double value1,value2,result;
HashSet resultSet = new HashSet();
//boolean success = false;
for (int i=0; i<6; i++) {
value1 = calValue(a.getElement(0),a.getElement(1),i);
for (int j=0; j<6; j++) {
value2 = calValue(value1,a.getElement(2),j);
for (int k=0; k<6; k++) {
result =calValue(value2,a.getElement(3),k);
if (result<=24.02 && result>=23.98) {
if (!success) success = true;
//load the result into a string array
//turn every number in result into string
String c[] = new String[8];
c[0] = Integer.toString((int)a.getElement(0));
c[1] = Integer.toString(i);
c[2] = Integer.toString((int)a.getElement(1));
c[3] = Integer.toString(j);
c[4] = Integer.toString((int)a.getElement(2));
c[5] = Integer.toString(k);
c[6] = Integer.toString((int)a.getElement(3));
c[7] = "A";
resultSet.add(c);
}
}
}
}

for (int i=0; i<6; i++) {
value1 = calValue(a.getElement(0),a.getElement(1),i);
for (int j=0; j<6; j++) {
value2 = calValue(a.getElement(2),a.getElement(3),j);
for (int k=0; k<6; k++) {
result =calValue(value1,value2,k);
if (result<=24.02 && result>=23.98) {
if (!success) success = true;
//load the result into a string array
//turn every number in result into string
String c[] = new String[8];
c[0] = Integer.toString((int)a.getElement(0));
c[1] = Integer.toString(i);
c[2] = Integer.toString((int)a.getElement(1));
c[3] = Integer.toString(k);
c[4] = Integer.toString((int)a.getElement(2));
c[5] = Integer.toString(j);
c[6] = Integer.toString((int)a.getElement(3));
c[7] = "B";
resultSet.add(c);

}
}
}
}
//if(!success) System.out.println("Calculation failed!");
return resultSet;
}

public HashSet work() {
HashSet permanentSet=new HashSet();
Iterator it = sourceSet.iterator();
while(it.hasNext())
permanentSet.addAll(work((MyArray)it.next()));
return permanentSet;
}

public boolean success() {return success;}

public static void main(String[] args) {
//Set sourceSet = HashSet();
//sourceSet = new input().rearrange(args)
Cal24 cal24 = new Cal24(args);
HashSet s = cal24.work();
if(cal24.success()) {
Output o = new Output();
o.resultTree(s);
o.prtResult();
}

}
}


class MyArray {
private double[] sourceData = new double[4];

MyArray(String[] source) {
for(int i=0; i<source.length; i++)
sourceData[i] = (double)Integer.parseInt(source[i]);

}

MyArray() {}

MyArray(MyArray a){
for (int i=0; i<a.getLength(); i++)
this.sourceData[i]=a.sourceData[i];
}

public int hashCode() {
return (int)(sourceData[0]*1000+sourceData[1]*100+sourceData[2]*10+sourceData[3]);
}

public void add(double d, int index) {
sourceData[index] = d;
}

public double get(int i) {
double d = sourceData[i];
int j = i+1;
for(; j<getLength(); j++)
sourceData[j-1] = sourceData[j];
sourceData[j-1]=0;
return d;
}

public double getElement(int i) {
return sourceData[i];
}

public int getLength() {
int j = 0;
for(int i=0; i<sourceData.length; i++)
if(sourceData[i]!=0) j++;
return j;
}

public boolean equals(Object o) {
return(o instanceof MyArray)&&(hashCode()==((MyArray)o).hashCode());
}

public String toString() {
String s = "{";
for(int i=0; i<getLength(); i++)
s+=(int)getElement(i)+",";
s+="}";
return s;
}
}


class input {
private Set inputSet = new HashSet();

public Set rearrange (MyArray a) {
MyArray getArray = new MyArray();
MyArray[] bufferArray = new MyArray[4];
for(int i=0; i<a.getLength(); i++) {
bufferArray[0] = new MyArray(a);
getArray.add(a.get(i),0);
for(int j=0; j<a.getLength(); j++) {
bufferArray[1] = new MyArray(a);
getArray.add(a.get(j),1);
for(int k=0; k<a.getLength(); k++) {
bufferArray[2] = new MyArray(a);
getArray.add(a.get(k),2);
for(int p=0; p<a.getLength();p++) {
bufferArray[3] = new MyArray(a);
getArray.add(a.get(p),3);
//System.out.println(getArray);
inputSet.add(new MyArray(getArray));
a = new MyArray(bufferArray[3]);
}
a = new MyArray(bufferArray[2]);
}
a = new MyArray(bufferArray[1]);
}
a = new MyArray(bufferArray[0]);
}
return inputSet;
}
}




wolfsquare 2004-04-13
  • 打赏
  • 举报
回复
// 接上


// 执行单次运算
public double caculate(int num1, String op1, int num2, String op2, int num3,
String op3, int num4) {
double ret = 0;

ret = caltwo(num1, op1, num2);
ret = caltwo(ret, op2, num3);
ret = caltwo(ret, op3, num4);

return ret;
}

/**
* 两元计算
* @param num1
* @param op
* @param num2
* @return
*/
private double caltwo(double num1, String op, double num2) {
double ret = 0;

if (op.equals("+")) {
ret = num1 + num2;
} else if (op.equals("-")) {
ret = num1 - num2;
} else if (op.equals("*")) {
ret = num1 * num2;
} else {
ret = num1 / num2;
}

return ret;
}

public void run() {
System.out.println("run");
this.jbtnstart.setEnabled(false);

int pos1 = 0;
int pos2 = 1;
int pos3 = 2;
int pos4 = 3;
double val = 0;
StringBuffer strb = new StringBuffer();
JProgressBar1.setMinimum(0);
JProgressBar1.setMaximum(13 * 13 * 13 * 13);

int step = 0;

if (listdata.size() > 0) {
listdata.removeAllElements();
}

int size = 0;

// 穷举法
for (pos1 = 0; (pos1 < 13) && !stopflag; pos1++)
for (pos2 = 0; (pos2 < 13) && !stopflag; pos2++)
for (pos3 = 0; (pos3 < 13) && !stopflag; pos3++)
for (pos4 = 0; (pos4 < 13) && !stopflag; pos4++) {
for (int i = 0; (i < 64) && !stopflag; i++) { // 四则运算全排列遍历
val = caculate(allnum[pos1], ops[i][0], allnum[pos2], ops[i][1],
allnum[pos3], ops[i][2], allnum[pos4]);

if (Math.abs(Math.abs(val) - 24) < precision) { // 绝对差超过最小精度的不算是整除
strb = new StringBuffer();
strb.append(String.valueOf(allnum[pos1]));
strb.append(ops[i][0]);
strb.append(String.valueOf(allnum[pos2]));
strb.append(ops[i][1]);
strb.append(String.valueOf(allnum[pos3]));
strb.append(ops[i][2]);
strb.append(String.valueOf(allnum[pos4]));
listdata.addElement(strb.toString());

if ((step % 100) == 0) {
JList1.setListData(listdata);
JList1.repaint();
}

// System.out.println(strb.toString() );
size++;
strb = new StringBuffer();
strb.append("当前进度:");
strb.append(String.valueOf(step + 1));
strb.append(" 符合个数:");
strb.append(size);
jlblmessage.setText(strb.toString());

break;
}
}

JProgressBar1.setValue(step++);
jlblmessage.repaint();
}

JList1.setListData(listdata);
JList1.repaint();
System.out.println("end");
this.jbtnstart.setEnabled(true);
}

public void stop() {
stopflag = !stopflag;
}

void jbtnstop_actionPerformed(ActionEvent e) {
stop();
}

void jbtncalculatesingle_actionPerformed(ActionEvent e) {
jbtncalculatesingle.setEnabled(false);

boolean ret = false;
double val = 0;
StringBuffer strb = null;
int[] num = { 0, 0, 0, 0 };

try {
num[0] = Integer.parseInt(jtxtopnum4.getText());
num[1] = Integer.parseInt(jtxtopnum3.getText());
num[2] = Integer.parseInt(jtxtopnum2.getText());
num[3] = Integer.parseInt(jtxtopnum1.getText());
} catch (Exception ex) {
}

int[][] n = new int[24][4];
int count = 0;

for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++) {
if (i == j) {
continue;
}

for (int k = 0; (i != j) && (k < 4); k++) {
if ((k == i) || (k == j)) {
continue;
}

for (int l = 0; l < 4; l++) {
if ((l == i) || (l == j) || (l == k)) {
continue;
}

n[count][0] = num[i];
n[count][1] = num[j];
n[count][2] = num[k];
n[count++][3] = num[l];
}
}
}

System.out.println("组合数:" + count);

listdata.removeAllElements();
JList1.repaint();

for (count--; (count >= 0) && !ret; count--)
for (int i = 0; (i < 64) && !ret; i++) {
val = caculate(n[count][0], ops[i][0], n[count][1], ops[i][1],
n[count][2], ops[i][2], n[count][3]);

strb = new StringBuffer();
strb.append(String.valueOf(n[count][0]));
strb.append(ops[i][0]);
strb.append(String.valueOf(n[count][1]));
strb.append(ops[i][1]);
strb.append(String.valueOf(n[count][2]));
strb.append(ops[i][2]);
strb.append(String.valueOf(n[count][3]));
listdata.addElement(strb.toString());

if (Math.abs(Math.abs(val) - 24) < precision) {
JLabel.setText(strb.toString());
ret = true;
}
}

JList1.repaint();

if (!ret) {
JLabel.setText(" 结果: 计算不出 " + val);
}

jbtncalculatesingle.setEnabled(true);
}
}
wolfsquare 2004-04-13
  • 打赏
  • 举报
回复
任意一个四则运算式子都能按运算符规则解开为顺序等价式,由于四则运算的枚举已经自然包含了所有可能性,因此不需要考虑四则运算的优先顺序,也不需考虑正负号
下面给出我的实现:

package test;

import java.awt.*;
import java.awt.event.*;

import java.math.*;

import java.util.Vector;

import javax.swing.*;


/**
*
24点计算程序
*
copyright:wolfsquare copyright (c) 2002
* 许可:
* 如果转载请注明出处,禁止将本代码用于商业用途.
* 改进或建议可与nnduke@163.com联系
* @author wolfsquare
* @version 1.0
*/
public class point24 extends JFrame implements Runnable {
private final static double precision = 0.1; // 允许和24的最小的差值精度
private static final String[] fontsettings = {
"checkbox.font", "tree.font", "viewport.font", "progressbar.font",
"radiobuttonmenuitem.font", "toolbar.font", "colorchooser.font",
"togglebutton.font", "panel.font", "textarea.font", "menu.font",
"tableheader.font", "textfield.font", "optionpane.font", "menubar.font",
"button.font", "label.font", "passwordfield.font", "scrollpane.font",
"menuitem.font", "tooltip.font", "list.font", "editorpane.font",
"table.font", "tabbedpane.font", "radiobutton.font", "checkboxmenuitem.font",
"textpane.font", "popupmenu.font", "titledborder.font",
"internalframe.titlefont", "combobox.font",
};
Vector listdata = new Vector();
boolean stopflag = false;
JPanel JPanel2 = new JPanel();
JButton jbtnstart = new JButton();
JButton jbtnstop = new JButton();

Thread Thread = new Thread(this);
String[] op = { "+", "-", "*", "/" };
String[][] ops = null;
int[] allnum;
private JPanel JPanel4 = new JPanel();
private BorderLayout BorderLayout1 = new BorderLayout();
private JPanel JPanel1 = new JPanel();
private JList JList1 = new JList(listdata);
private JLabel JLabel = new JLabel("结果:");
private JTextField jtxtopnum1 = new JTextField();
private JTextField jtxtopnum2 = new JTextField();
private JTextField jtxtopnum3 = new JTextField();
private JTextField jtxtopnum4 = new JTextField();
private JScrollPane JScrollPane1 = new JScrollPane();
private JSplitPane JSplitPane1 = new JSplitPane();
private BorderLayout BorderLayout2 = new BorderLayout();
private JProgressBar JProgressBar1 = new JProgressBar();
private GridLayout GridLayout1 = new GridLayout(6, 1);
private JButton jbtncalculatesingle = new JButton();
private JPanel JPanel3 = new JPanel();
private JLabel jlblmessage = new JLabel();

public point24() {
try {
jbinit();
} catch (Exception e) {
e.printStackTrace();
}

initdata();
}

public static void setfont() {
Font defaultfont = new Font("宋体", Font.PLAIN, 12);

for (int i = 0; i < fontsettings.length; i++) {
UIManager.put(fontsettings[i], defaultfont);
}
}

public static void main(String[] args) {
point24 frame2 = new point24();
frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame2.show();
}

private void jbinit() throws Exception {
setfont();
this.setSize(new Dimension(400, 300));
jbtnstart.setText("start");
jbtnstart.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
jbtnstart_actionPerformed(e);
}
});
jbtnstop.setText("stop");
jbtnstop.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
jbtnstop_actionPerformed(e);
}
});
JPanel4.setLayout(BorderLayout1);
JPanel1.setLayout(BorderLayout2);
jbtncalculatesingle.setText("计算");
jbtncalculatesingle.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(ActionEvent e) {
jbtncalculatesingle_actionPerformed(e);
}
});
JPanel3.setLayout(GridLayout1);
jlblmessage.setText("状态");
JPanel2.setBorder(BorderFactory.createEtchedBorder());
this.getContentPane().add(JPanel2, BorderLayout.SOUTH);
JPanel2.add(jbtnstart, null);
JPanel2.add(jbtnstop, null);
this.getContentPane().add(JPanel4, BorderLayout.CENTER);
JPanel4.add(JSplitPane1, BorderLayout.CENTER);
JPanel1.add(JProgressBar1, BorderLayout.SOUTH);
JPanel1.add(JScrollPane1, BorderLayout.CENTER);
JSplitPane1.add(JPanel3, JSplitPane.TOP);
JScrollPane1.getViewport().add(JList1, null);
JSplitPane1.add(JPanel1, JSplitPane.BOTTOM);
JPanel3.add(JLabel, null);
JPanel3.add(jtxtopnum1, null);
JPanel3.add(jtxtopnum2, null);
JPanel3.add(jtxtopnum3, null);
JPanel3.add(jtxtopnum4, null);
JPanel3.add(jbtncalculatesingle, null);
JPanel4.add(jlblmessage, BorderLayout.SOUTH);
JSplitPane1.setDividerLocation(200);
this.setTitle("24点计算");
}

void jbtnstart_actionPerformed(ActionEvent e) {
Thread.start();
}

private void initdata() {
allnum = new int[13];

// 产生1-13数字
for (int i = 0, n = 1; i < 13; i++, n++) {
allnum[i] = n;
}

for (int i = 0; i < 13; i++)
System.out.print(" " + allnum[i]);

// 运算符全排列
ops = new String[64][3];

for (int i = 0, n = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
for (int k = 0; k < 4; k++, n++) {
ops[n][0] = op[i];
ops[n][1] = op[j];
ops[n][2] = op[k];
}
}

// (未完)第一部分
evilzydar 2004-04-13
  • 打赏
  • 举报
回复
mark!
学习!
flyforlove 2004-04-13
  • 打赏
  • 举报
回复
不用括号可以么?
如果是这个形式,8/(3-8/3)=24
不用括号怎么得到?很显然没有办法化简。
wolfsquare 2004-04-13
  • 打赏
  • 举报
回复
不需要考虑括号,因为考虑穷举排列组合时,已经包含所有运算顺序了.
但是一定要考虑小数运算及其造成的误差.
楼上说的用Python的多少行的,也不想想可以这么说:如果别人写了一个库专门算24点,那岂不是最多只要用一条语句就完成了计算24点?
加载更多回复(15)

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧