离散数学上机题---求命题的主范式

该博客介绍了一个功能,输入命题公式的合式公式,可求出其真值表,并输出主合取范式和主析取范式。还说明了输入公式的符号含义,如! 表示非,& 表示与等,同时规定了输出形式。

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

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

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

输入公式的符号说明:

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

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

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

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

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

( 前括号

) 后括号

#include<bits/stdc++.h>
using namespace std;
char expression[100];
int alphbet[26]={0};
int pos[30] = {0};
int k = 0;
int get_priority(char a){
    int re = 0;
    switch (a){
    case '(':re = 1;break;
    case '!':re = 8;break;
    case '|':re = 6;break;
    case '&':re = 7;break;
    case '-':re = 4;break;
    case '+':re = 3;break;
    }
    return re;
}
void addsome(){
    alphbet[pos[0]]++;
    for(int i = 0;i < k-1;i++){
        if(alphbet[pos[i]] > 1){
            alphbet[pos[i+1]] += 1;
            alphbet[pos[i]] = 0;
        }
    }
    //for(int i =0 ;i< k;i++) cout << alphbet[pos[i]] << " ";
    //cout << endl;
}
bool calc(int num){
    stack < bool > value;bool tmp1,tmp2;
    // for(int j = 0;j < k-1;j++){
    //     cout << alphbet[pos[j]] << ",";
    // }
    // cout << endl;
    for(int j = 0;j < num;j++){
        //利用栈计算真值
        switch(expression[j]){
            case 'z': value.push(alphbet[expression[j] - 'a']);break;
            case '!': tmp1 = value.top();value.pop();value.push(!tmp1);break;
            case '|': tmp1 = value.top();value.pop();tmp2 = value.top();value.pop();
                    value.push(tmp1 || tmp2);break;
            case '&':tmp1 = value.top();value.pop();tmp2 = value.top();value.pop();
                    value.push(tmp1 && tmp2);break;
            case '-':tmp2 = value.top();value.pop();tmp1 = value.top();value.pop();
                    if(tmp1 == true && tmp2 == false){
                        value.push(false);
                    }else{
                        value.push(true);
                    }break;
            case '+': tmp1 = value.top();value.pop();tmp2 = value.top();value.pop();
                    value.push(tmp1 == tmp2);break;
            default : break;
        }
    }
    return value.top();
}
int main(){
    stack <char> ops;
    // 用于记录字母位置,同时便于枚举所有“赋值”进行真值计算的数组
    
    //用于记录成真赋值
    int real[30] = {0};
    //记录成假赋值
    int notruth[30] = {0};
    int i = 0,realint = 0,notint = 0;
    char c;
    // 中缀转后缀,后缀表达式保存在一个数组中
    while((c = getchar()) != '\n'){
        //if(c == ' ') continue;
        //cout << c << endl;
        if((c >= 'a') && (c <= 'z')){ 
            //---------------------------------------c是操作数
            
                expression[i++] = c;//字母放到后缀数组中
                alphbet[c-'a']++;//方便后续统计出现多少种字母,对每种字母进行赋值
            
        }else{
            // -------------------------------------------c为操作符
            if(ops.empty() || c == '('){
                ops.push(c);
            }else{
                if(c == ')'){
                    while(ops.top() != '('){
                        expression[i++] = ops.top();
                        ops.pop();
                    }
                    ops.pop();
                }else if(get_priority(c) > get_priority(ops.top())){
                    ops.push(c);
                }else{
                    while(!ops.empty() && get_priority(c) < get_priority(ops.top())){
                        expression[i++] = ops.top();ops.pop();
                    }
                    ops.push(c);
                }
            }
        }
    }
    //输入结束弹空栈
    while(!ops.empty()){
        expression[i++] = ops.top();
        ops.pop();
    }
    //cout << "end" << endl;
    //for(i-1;i+1;i--) cout << expression[i] << " " ;

    // 枚举,计算,保留结果
    
    for(int j = 25;j + 1;j--){
        if(alphbet[j]) pos[k++] = j;
    }
    //cout << k << endl;
    int scal = 1;
    memset(alphbet,0,sizeof(alphbet));
    for(int j = 1;j <= k;j++) scal *= 2;
    scal -= 1;
    //cout << k << endl;
    if(calc(i)) real[realint++] = 0;
    else notruth[notint++] = 0;
    for( int j = 1;j <= scal;j++){
        //枚举
        addsome();
        if(calc(i)) real[realint++] = j;
        else notruth[notint++] = j;
    }
    // 输出 
    if(realint == 0){
        // 永假式
        cout << "0 ; ";
    }else{
        for(int j = 0;j < realint-1;j++){
            cout << "m" << real[j] << " ∨";
            cout << " ";
        }
        cout << "m" << real[realint - 1] << " ; ";
    }
    if(!notint){
        //永真式
        cout << "1" << endl;
    }else{
        for(int j = 0;j < notint-1;j++){
            cout << "M" << notruth[j] << " ∧ ";
        }
        cout << "M" << notruth[notint-1] << endl;
    }
    return 0;
}

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值