分享一段計算24點的程序,後綴表達式計算

//分享一段計算24點的程序,用後綴表達式計算,自己寫的,全排列算法來自網絡,沒有轉化成利於閱讀的中綴表達式

//可以繼續優化,並轉換成中綴表達式,去掉重複的(例如先後順序的差異)

import java.util.Stack;

////winion 2020-5-10
public class Main {

    static char[] ops = new char[] { '?', '?', '+', '-', '*', '/' };

    static int count = 0;

    //數字的全排列
    public static void permutation(char[] ss, int i) {
        if (ss == null || i < 0 || i > ss.length) {// 1
            return;
        }
        if (i == ss.length - 1) {// 2
            gen(ss);
        } else {
            for (int j = i; j < ss.length; j++) {// 3
                char temp = ss[j];// 交換前綴,使之產生下一個前綴
                ss[j] = ss[i];
                ss[i] = temp;
                permutation(ss, i + 1);// 4
                temp = ss[j]; // 將前綴換回來,繼續做上一個的前綴排列.//5
                ss[j] = ss[i];
                ss[i] = temp;
            }
        }
    }

    public static void gen(char[] ss) {
        char[] opstr = new char[7];
        opstr[0] = ss[0];
        opstr[1] = ss[1];

        ops[0] = ss[2];
        ops[1] = ss[3];
        int opcount = 0;
        int curr = 2;
        //循環產生所有的表達式組合,此處可以優化,少循環幾次
        for (int i = 0; i < ops.length; i++) {
            opstr[curr++] = ops[i];
            for (int j = 0; j < ops.length; j++) {
                opstr[curr++] = ops[j];
                for (int l = 0; l < ops.length; l++) {
                    opstr[curr++] = ops[l];
                    for (int m = 0; m < ops.length; m++) {
                        opstr[curr++] = ops[m];
                        for (int n = 0; n < ops.length; n++) {
                            opstr[curr++] = ops[n];
                            // 判斷是否合法,運算符的數量是三個,數字兩個且無重複,另外兩個在開頭,不用計算
                            opcount = 0;
                            for (int p = 2; p < opstr.length; p++) {
                                if (opstr[p] == '+' || opstr[p] == '-' || opstr[p] == '*' || opstr[p] == '/') {
                                    opcount++;
                                }
                            }
                            if (opcount == 3) {
                                // 判斷是否有重複數字
                                char exists = '0';
                                for (int p = 2; p < opstr.length; p++) {
                                    if (opstr[p] >= '1' && opstr[p] <= '6') {
                                        if (exists == '0')
                                            exists = opstr[p];
                                        else if (exists != '0' && exists == opstr[p]) {
                                            exists = 'E';//E代表有重複了
                                            break;
                                        }
                                    }
                                }
                                if (exists == '0' || exists != 'E') {
                                    float re = calc(opstr);
                                    System.out.println(new String(opstr) + "=" + re);
                                    if (re > 0)
                                        count++;
                                }
                            }
                            curr--;
                        }
                        curr--;
                    }
                    curr--;
                }
                curr--;
            }
            curr--;
        }
    }

    public static float calc(char[] opstr) {
        Stack<Float> temp = new Stack<>();
        for(int i=0;i<opstr.length;i++) {
            char c1 =opstr[i];
            if (c1 > '0' && c1 <= '6') {
                temp.push((int) (c1 - '0') + 0f);
            } else {
                // 運算符,每遇到一個運算符將計算棧裏的數據
                if (temp.size() >= 2) {
                    float t1 = temp.pop();
                    float t2 = temp.pop();
                    if (c1 == '+') {
                        temp.push(t1 + t2);
                    } else if (c1 == '-') {
                        temp.push(t2 - t1);
                    } else if (c1 == '*') {
                        temp.push(t1 * t2);
                    } else if (c1 == '/') {
                        temp.push(t2 / t1);
                    }
                } else {
                    //如果棧裏的數據不夠,說明表達式錯誤
                    return -1f;
                }
            }
        }
        return temp.pop();
    }

    public static void main(String args[]) {
        permutation(new char[] { '6', '5', '4', '1' }, 0);
        System.out.println(count);
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章