北理工离散数学上机实验:求命题公式的主范式

题目要求:

实现功能:输入命题公式的合式公式,求出公式的真值表,并输出该公式的主合取范式和主析取范式。

输入:命题公式的合式公式

输出:公式的主析取范式和主析取范式,输出形式为:“ mi ∨ mj ; Mi ∧ Mj” ,极小项和 ∨ 符号之间有一个空格,极大项和 ∧ 符号之间有一个空格;主析取范式和主合取范式之间用“ ; ”隔开,“ ; ”前后各有一个空格。 永真式的主合取范式为 1 ,永假式的主析取范式为 0 。

输入公式的符号说明:

! 非,相当于书面符号中的 “ ¬ ”

& 与,相当于书面符号中的 “ ∧ ”

| 或,相当于书面符号中的 “ ∨ ”

- 蕴含联结词,相当于书面符号中的 “ → ”

+ 等价联结词,相当于书面符号中的 “ ↔ ”

( 前括号

) 后括号

整体思路:

1、将表达式转化成逆波兰式(后缀表达式),这个大家如果C语言课认真学的话,大一的乐学练习是有的,这个是笔者觉得最重要的一部分,只有这个部分做好才能把后续弄好。

2、根据逆波兰式,从00000....到11111.....依次遍历赋值,计算表达式的值(这个赋值过程也需要一定时间构思代码)

3、根据计算的结果,输出主范式。

全部代码:

#include<iostream>
#include<cmath>
#include<string>
#include<cstring>
using namespace std;
int op_rank(char a){
    switch (a)
    {
    case '(':return 0;
    case '+':return 1;
    case '-':return 2;
    case '&':return 3;
    case '|':return 4;
    case '!':return 5;
    case ')':return 6;
    }
}
bool is_in(char a,string x){
    for(unsigned int i=0;i<x.size();i++){
        if (x[i]==a) return true;
    }
    return false;
}
string post_rpn(string &input){
    string stack,output;
    int b=0;
    for(unsigned int i=0;i<input.size();i++){
        if(is_in(input[i],"()+-&|!")){
            if(input[i]==')'){
                while(stack[stack.size()-1]!='('){
                    output+=stack[stack.size()-1];
                    stack.erase(stack.begin()+stack.size()-1);
                }
                stack.erase(stack.begin()+stack.size()-1);
            }
            else{
                while((stack.size()!=0)&&op_rank((stack[stack.size()-1]))>=op_rank(input[i])&&input[i]!='('){
                    output+=stack[stack.size()-1];
                    stack.erase(stack.begin()+stack.size()-1);
                }
                stack+=input[i];
            }
        }
        else output+=input[i];
    }
    while(stack.size()!=0) {
        output+=stack[stack.size()-1];
        stack.erase(stack.begin()+stack.size()-1);
    }
    return output;
}
string how_mang_elements(string a){
    string b="";
    for(unsigned int i=0;i<a.size();i++){
        if(a[i]>='a'&&a[i]<='z'&&!is_in(a[i],b)){
            b+=a[i];
        }
    }
    for(unsigned int x=0;x<b.size();x++){
        for(unsigned int y=0;y<b.size()-x-1;y++){
            if(a[y]>a[y+1]){
                char c=a[y];
                a[y]=a[y+1];
                a[y+1]=c;
            }
        }
    }
    return b;
}
int cal(int a,int b,char c){
    if(c=='+'){
        if(a==b) return 1;
        else return 0;
    }
    else if(c=='-'){
        if(a==1&&b==0) return 0;
        else return 1;
    }
    else if(c=='|'){
        if(a+b>=1) return 1;
        else return 0;
    }
    else if(c=='&') {return a*b;}
    else if(c=='!') {
        if(a==1) return 0;
        else return 1;
    }
}
int calculate(string a){
    while(a.size()>1){
        for(unsigned int i=0;i<a.size();i++){
        if(is_in(a[i],"+|&-!")){
            if(a[i]!='!'){
                a[i-2]=char(cal(int(a[i-2]-'0'),int(a[i-1]-'0'),a[i])+'0');
                a.erase(a.begin()+i-1);
                a.erase(a.begin()+i-1);
                break;
            } 
            else{
                a[i-1]=char(cal(int(a[i-1]-'0'),0,a[i])+'0');
                a.erase(a.begin()+i);
                break;
            }
        }
        }
    }
    return int(a[0]-'0');
}
bool is_in2(int a,int *x,int d){
    for(int i=0;i<d;i++){
        if (x[i]==a) return true;
    }
    return false;
}
bool is_in3(int n,int i0,int *x,int d){
    for(int i=i0+1;i<n;i++){
        if(!is_in2(i,x,d)) return true;
    }
    return false;
}
void PRINT(int *n,string number,int d){
    if(d==0){
        cout<<"0"<<" ; ";
    }
    for(int i=0;i<d;i++){
        if((i!=d-1)&&is_in2(n[i],n,d)){
            cout<<"m"<<n[i]<<" ∨ ";
        }
        else if(is_in2(n[i],n,d)){
            cout<<"m"<<n[i]<<" ; ";
        }
    }
    for(int i=0;i<pow(2,number.size());i++){
        if(!is_in3(pow(2,number.size()),-1,n,d)){
            cout<<"1"<<endl;
            break;
        }
        else {if(!is_in2(i,n,d)&&is_in3(pow(2,number.size()),i,n,d)){
            cout<<"M"<<i<<" ∧ ";
        }
        else if(!is_in2(i,n,d)){
            cout<<"M"<<i<<endl;
        }}
    }
    
}
int where_is_element(string number0,char a){
    for(int i=0;i<number0.size();i++){
        if(number0[i]==a) return i;
    }
}
void bianli(string number,string output2){
    string a="",number0=number;
    int c[500],d=0;
    for(int i=0;i<pow(2,number.size());i++){
        int p=i;
        a="";
        while(p!=0){
            a=char(p%2+'0')+a;
            p=p>>1;
        }
        int b=0;
        for(unsigned int j=0;j<number.size();j++){
            if(a.size()<number.size()-j) number[j]='0';
            else number[j]=a[b++];
        }
        string output=output2;
        for(unsigned int i=0;i<output.size();i++){
            if(output[i]>='a'&&output[i]<='z') {
                output[i]=number[where_is_element(number0,output[i])];
            }
        }
        if(calculate(output)==1) {c[d++]=i;}

    }
    PRINT(c,number,d);
}
int main(void){
    string input;
    cin>>input;
    bianli(how_mang_elements(post_rpn(input)),post_rpn(input));
}

代码较为简单,请读者自行分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值