栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

对任意合式公式求真值表以及主析取范式和主合取范式(JAVA)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

对任意合式公式求真值表以及主析取范式和主合取范式(JAVA)

话不多说直接上代码

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
import java.util.Stack;

public class Solution {

    static char[] alpha;
    static String result;
    static HashMap map = new HashMap();//键值对
    static ArrayList> trueList = new ArrayList>();//结果为真的列表,用于计算主析取范式
    static ArrayList> falseList = new ArrayList>();//结果为假的列表,用于计算主合取范式

    public static String preProcess(String str) {//预处理
        boolean flag = true;
        int cur = 0;
        while (flag) {
            flag = false;
            for (int i = cur; i < str.length(); i++) {
                if (str.charAt(i) == '<' || str.charAt(i) == '>') {//对于->和<=>两种符号,这里把<>都去掉,以-和=代替
                    String str1 = str.substring(0, i);
                    String str2 = str.substring(i + 1, str.length());
                    str = str1.concat(str2);
                    flag = true;
                    cur = i;
                    break;
                }
                if(str.charAt(i) == '!') {//对于连续的!, 先统计共有多少i
                    int count = 1;
                    while(str.charAt(i + count) == '!') {
                        count++;
                    }
                    if(count % 2 == 1) {//奇数个!,则取第一个!,跳过中间偶数个!
                        String str1 = str.substring(0, i + 1);
                        String str2 = str.substring(i + count, str.length());
                        str = str1.concat(str2);
                        flag = true;
                        cur = i + 1;//下一次遍历从新str的!后一个字符开始遍历
                        break;
                    }else {//偶数个!,则跳过所有!
                        String str1 = str.substring(0, i);
                        String str2 = str.substring(i + count, str.length());
                        str = str1.concat(str2);
                        flag = true;
                        cur = i;//下一次遍历从新的str的记录点开始遍历
                        break;
                    }
                }
            }
        }
        return str;
    }

    public static String RPN(String str) {//逆波兰
        char[] chars = str.toCharArray();
        int pre = 0;
        boolean charactor; // 是否为字母(只要不是运算符,都是字母),用于截取字符串
        int len = chars.length;
        int bracket = 0; // 左括号的数量
        String result = "";
        Stack output = new Stack();
        Stack operators = new Stack<>();

        for (int i = 0; i < len;) {
            pre = i;
            charactor = Boolean.FALSE;
            // 截取数字
            while (i < len && !Operator.isOperator(chars[i])) {
                i++;
                charactor = Boolean.TRUE;
            }

            if (charactor) {
                output.push(str.substring(pre, i));
            } else {
                char o = chars[i++]; // 运算符
                if (o == '(') {
                    bracket++;
                }
                if (bracket > 0) {
                    if (o == ')') {
                        while (!operators.empty()) {
                            char top = operators.pop();
                            if (top == '(') {
                                break;
                            }
                            output.push(top);
                        }
                        bracket--;
                    } else {
                        // 如果栈顶为 ( ,则直接添加,不顾其优先级
                        // 如果之前有 ( ,但是 ( 不在栈顶,则需判断其优先级,如果优先级比栈顶的低,则依次出栈
                        while (!operators.empty() && operators.peek() != '('
                                && Operator.cmp(o, operators.peek()) <= 0) {
                            output.push(operators.pop());
                        }
                        operators.push(o);
                    }
                } else {
                    while (!operators.empty() && Operator.cmp(o, operators.peek()) <= 0) {
                        output.push(operators.pop());
                    }
                    operators.push(o);
                }
            }

        }
        // 遍历结束,将运算符栈全部压入output
        while (!operators.empty()) {
            output.push(operators.pop());
        }

        while (!output.isEmpty()) {
            result = output.pop() + result;
        }
        return result;
    }

    public static String alphaTable(String str) {//得出公式字母表
        char[] carray = str.toCharArray();
        String alpha = "";
        for(int i = 0; i < str.length(); i++) {
            if((carray[i] >= 'A' && carray[i] <= 'Z') || (carray[i] >= 'a' && carray[i] <= 'z')) {
                alpha = alpha + carray[i];
            }
        }
        return alpha;
    }

    public static boolean calculate(String str) {//计算公式,得出结果值
        Stack calStack = new Stack();
        char[] carray = str.toCharArray();
        boolean cur, pre, post, result;
        for(int i = 0; i < str.length(); i++) {
            if(carray[i] == '!') {
                cur = calStack.pop();
                result = !cur;
            }else if(carray[i] == '&') {
                post = calStack.pop();
                pre = calStack.pop();
                result = pre && post;
            }else if(carray[i] == '|') {
                post = calStack.pop();
                pre = calStack.pop();
                result = pre || post;
            }else if(carray[i] == '-') {
                post = calStack.pop();
                pre = calStack.pop();
                if(pre == true && post == false) {
                    result = false;
                }else {
                    result = true;
                }
            }else if(carray[i] == '=') {
                post = calStack.pop();
                pre = calStack.pop();
                if(pre == post) {
                    result = true;
                }else {
                    result = false;
                }
            }else{
                result = map.get(carray[i]);
            }
            calStack.push(result);
        }
        return calStack.peek();
    }

    public static void dfs(int cur) {//遍历,赋每个字母真假值	进真假表
        if(cur == alpha.length) {
            boolean ans = calculate(result);
            ArrayList aL = new ArrayList();
            for(int i = 0; i < alpha.length; i++) {
                aL.add(map.get(alpha[i]));
                System.out.printf("%ct", map.get(alpha[i]) == true ? 'T' : 'F');
            }
            if(ans) {
                trueList.add(aL);
                System.out.println('T');
            }else {
                falseList.add(aL);
                System.out.println('F');
            }
            return;
        }
        map.put(alpha[cur], true);
        dfs(cur + 1);
        map.put(alpha[cur], false);
        dfs(cur + 1);
    }

    public static void printTable() {//打印真值表
        System.out.println("真值表为");
        for(int i = 0; i < alpha.length; i++) {
            System.out.printf("%ct", alpha[i]);
        }
        System.out.println("A");
        for(int i = 0; i < alpha.length * 9; i++) {
            System.out.print('-');
        }
        System.out.println();
        dfs(0);
    }

    public static void printFormula() {//打印主析取范式和主合取范式
        System.out.println("主析取范式为");
        for(int i = 0; i < trueList.size(); i++) {
            System.out.print("(");
            for(int j = 0; j < trueList.get(i).size(); j++) {
                if(trueList.get(i).get(j) == true) {
                    System.out.print(alpha[j]);
                }else {
                    System.out.print("┐" + alpha[j]);
                }
                if(j != trueList.get(i).size() - 1) {
                    System.out.print("∧");
                }
            }
            System.out.print(")");
            if(i != trueList.size() - 1) {
                System.out.print("∨");
            }
        }
        System.out.println();
        System.out.println("主合取范式为");
        for(int i = 0; i < falseList.size(); i++) {
            System.out.print("(");
            for(int j = 0; j < falseList.get(i).size(); j++) {
                if(falseList.get(i).get(j) == false) {
                    System.out.print(alpha[j]);
                }else {
                    System.out.print("┐" + alpha[j]);
                }
                if(j != falseList.get(i).size() - 1) {
                    System.out.print("∨");
                }
            }
            System.out.print(")");
            if(i != falseList.size() - 1) {
                System.out.print("∧");
            }
        }

    }

    public static void main(String[] args) {

        String str = "";
        System.out.println("请输入公式");
        System.out.println("&: 与运算, |: 或运算, !: 非运算, ->: 单条件运算, <=>: 双条件运算, (): 左右括号");
        Scanner scanner = new Scanner(System.in);
        str = scanner.nextLine();//读取公式
        scanner.close();
        
        String pstr = preProcess(str);//预处理
        result = RPN(pstr);//后缀表达式
        alpha = alphaTable(result).toCharArray();//字母表
        printTable();//打印真值表
        printFormula();//打印主析取范式,主合取范式
    }
}


enum Operator {//符号操作符枚举
    AND('&', 1), OR('|', 1), SINGLE('-', 1), DOUBLE('=', 1), NOT('!', 2), LEFT_BRACKET('(', 3), RIGHT_BRACKET(')', 3); // 括号优先级最高

    char value;
    int priority;

    Operator(char value, int priority) {
        this.value = value;
        this.priority = priority;
    }

    public static int cmp(char c1, char c2) {//比较优先级
        int p1 = 0;
        int p2 = 0;
        for (Operator o : Operator.values()) {
            if (o.value == c1) {
                p1 = o.priority;
            }
            if (o.value == c2) {
                p2 = o.priority;
            }
        }
        return p1 - p2;
    }

    public static boolean isOperator(char c) {//是否为操作符
        for (Operator o : Operator.values()) {
            if (o.value == c) {
                return true;
            }
        }
        return false;
    }
}

有问题可留言

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/361146.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号