枚举真值表生成主合取范式 主析取范式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了枚举真值表生成主合取范式 主析取范式相关的知识,希望对你有一定的参考价值。

方法:将表达式转化为后缀表达式->枚举真值表->输出其合取析取范式

  1 #include<stdio.h>
  2 #include<string.h>
  3 #define maxn 5000
  4 char s[maxn];
  5 int tail[maxn];
  6 int lens, lent;
  7 int stack[maxn];
  8 int spt;
  9 int num = 0;
 10 int maps[maxn];
 11 int unmaps[maxn];
 12 void push(int c) {
 13     stack[spt++] = c;
 14 }
 15 int top() {
 16     return stack[spt - 1];
 17 }
 18 void pop() {
 19     if (spt>0) spt--;
 20     else spt = 0;
 21 }
 22 void init() {
 23     spt = 0;
 24 }
 25 void error() {
 26     printf("表达式错误\n");
 27 }
 28 int l, r;
 29 void stack_deal(int pt) {
 30     while (spt>0 && top() <= pt) {
 31         tail[lent++] = -1 * top(); pop();
 32     }
 33     push(pt);
 34 }
 35 void out(int pt) {
 36     if (pt>0) {
 37         printf("%c ", unmaps[pt]);
 38         return;
 39     }
 40     pt *= -1;
 41     if (pt == 1) printf("!");
 42     if (pt == 2) printf("&");
 43     if (pt == 3) printf("|");
 44     if (pt == 4) printf("->");
 45     if (pt == 5) printf("<->");
 46     printf(" ");
 47 }
 48 int trans_tail(char s[]) {
 49     init();
 50     memset(maps, 0, sizeof(maps));
 51     memset(unmaps, 0, sizeof(unmaps));
 52     lent = 0;
 53     l = r = 0;
 54     num = 0;
 55     for (int i = 0; i<lens; i++) {
 56         int pt; if ((s[i] >= a&&s[i] <= z) || (s[i] >= A&&s[i] <= Z)) {
 57             if (maps[s[i]] == 0) {
 58                 num++; maps[s[i]] = num;
 59                 unmaps[num] = s[i];
 60             }
 61             tail[lent++] = maps[s[i]]; continue;
 62         }
 63         else if (s[i] == ~ || s[i] == !)
 64             stack_deal(1);
 65         else if (s[i] == &)
 66             stack_deal(2);
 67         else if (s[i] == |)
 68             stack_deal(3);
 69         else if (s[i] == -) {
 70             if (s[i + 1] == >) {
 71                 i++;
 72                 stack_deal(4);
 73             }
 74             else {
 75                 error(); return 0;
 76             }
 77         }
 78         else if (s[i] == <) {
 79             if (s[i + 1] == -&&s[i + 2] == >) {
 80                 i += 2;
 81                 stack_deal(5);
 82             }
 83             else {
 84                 error(); return 0;
 85             }
 86         }
 87         else if (s[i] == () {
 88             push(6); l++;
 89         }
 90         else
 91             if (s[i] == )) {
 92                 r++;
 93                 if (l <= 0) {
 94                     error(); return 0;
 95                 }
 96                 while (spt>0 && top() != 6) {
 97                     //    printf("add:%d %d\n",top(),spt);
 98                     tail[lent++] = -1 * top(); pop();
 99                 }//    printf("this:%d\n",top());
100                 pop(); l--; r--;
101             }
102             else {
103                 error(); return 0;
104             }
105     }
106     while (spt>0) {
107         tail[lent++] = -1 * top(); pop();
108     }
109     /*    printf("%d\n",lent);
110     for(int i=0;i<lent;i++)
111     out(tail[i]);*/
112     void out_ans();
113     out_ans();
114 }
115 typedef long long ll;
116 int bl[maxn];
117 ll ans1[100000], ans0[100000];
118 ll ansnum1 = 0, ansnum0 = 0;
119 void out_ans() {
120     ll upnum = (1LL << (num));
121     int dy = 0;
122     ansnum1 = ansnum0 = 0;
123     printf("是否打印真值表(1 yes 0 no)?\n");
124     scanf("%d", &dy);
125     if (dy) {
126         for (int i = 1; i <= num; i++) {
127             printf("%c ", unmaps[i]);
128         }
129         printf("\tans\n");
130     }
131     for (ll i = 0; i<upnum; i++) {
132         //    printf("%lld\n",ll);
133         ll bit = i;
134         for (int j = num; j>0; j--) {
135             bl[j] = bit&(1LL);
136             bit = bit >> 1;
137         }
138         init();
139         for (int j = 0; j<lent; j++) {
140             if (tail[j]>0) {
141                 //    printf("*%d %d\n",j,maps[tail[j]]);
142                 push(bl[tail[j]]);
143             }
144             else if (tail[j]<0) {
145                 int a, b;
146                 if (tail[j] == -1) {
147                     if (spt>0) {
148                         a = top(); pop();
149                     }
150                     else {
151                         error(); return;
152                     }
153                     a = !a;
154                     push(a); continue;
155                 }
156                 if (spt>1) { a = top(); pop(); b = top(); pop(); }
157                 else {
158                     error; return;
159                 }
160                 int c;
161                 if (tail[j] == -2) {
162                     c = a&&b;
163                     //printf("%d %d %d\n",a,b,c);
164                     push(c);
165                 }
166                 else if (tail[j] == -3) {
167                     c = a || b;
168                     push(c);
169                 }
170                 else if (tail[j] == -4) {
171                     c = 1;
172                     if (!a&&b) c = 0;
173                     push(c);
174                 }
175                 else if (tail[j] == -5) {
176                     c = 0;
177                     if (a&&b) c = 1;
178                     if (!a && !b) c = 1;
179                     push(c);
180                 }
181             }
182         }
183         if (dy) {
184             for (int j = 1; j <= num; j++) {
185                 printf("%d ", bl[j]);
186             }
187             printf("\t%d\n", top());
188         }
189         if (top() == 1) ans1[ansnum1++] = i;
190         if (top() == 0) ans0[ansnum0++] = i;
191     }
192     dy = 0;
193     printf("是否输出主合取范式?1 yes 0 no\n");
194     scanf("%d", &dy);
195     if (dy) {
196         for (int i = 0; i<ansnum0; i++) {
197             int np = ans0[i];
198             printf("(");
199             for (int j = num; j>0; j--) {
200                 int ws = np & 1; np = np >> 1;
201                 if (ws) {
202                     printf("");
203                 }
204                 printf("%c", unmaps[j]);
205                 if (j>1) printf("");
206             }
207             printf(")");
208             if (i<ansnum0 - 1) printf("");
209         }
210         printf("\n");
211     }
212     dy = 0;
213     printf("是否输出主析取范式?1 yes 0 no\n");
214     scanf("%d", &dy);
215     if (dy) {
216         for (int i = 0; i<ansnum1; i++) {
217             int np = ans1[i];
218             printf("(");
219             for (int j = num; j>0; j--) {
220                 int ws = np & 1; np = np >> 1;
221                 if (!ws) {
222                     printf("");
223                 }
224                 printf("%c", unmaps[j]);
225                 if (j>1) printf("");
226             }
227             printf(")");
228             if (i<ansnum1 - 1) printf("");
229         }
230         printf("\n");
231     }
232 }
233 void deal() {
234     printf("\n请输入式子:\n");
235     scanf("%s", s);
236     lens = strlen(s);
237     trans_tail(s);
238 }
239 int main() {
240     printf("输入时请用\n!代表┐\n&代表∧\n|代表∨\n->代表蕴含(减号和大于号)\n<->代表等值(小于号 减号 大于号)\n命题变元用任意大小写字母表示 ");
241     while (1) deal();
242 }

 

以上是关于枚举真值表生成主合取范式 主析取范式的主要内容,如果未能解决你的问题,请参考以下文章

Python(离散数学实验)求不超过4个命题变元任意公式的主合取范式主析取范式真值表和成真赋值

数理逻辑命题逻辑的等值演算与推理演算 ( 命题逻辑 | 等值演算 | 主合取 ( 析取 ) 范式 | 推理演算 ) ★★

将命题转化为主析取命范式和主合取范式

将析取范式转化为主析取范式

以合取范式书写条件

关于合取范式中的公式,下列哪项是正确的?