📄 boole.cc.txt
字号:
// Problem Boolean Logic// Algorithm Parser, Brute-Force// Runtime O(2^n)// Author Walter Guttmann// Date 13.07.2003#include <cassert>#include <cctype>#include <fstream>#include <iostream>#include <map>#include <queue>#include <stack>#include <string>using namespace std;ifstream in("boole.in");typedef queue<int> qi;typedef stack<int> si;typedef vector<int> vi;typedef map<char,int> mci;bool binary(char ch){ // ... conjunction, disjunction, implication, equivalence return ch == '&' || ch == '|' || ch == '-' || ch == '<';}// The semantics of the operators, lifted to characters.// If op is unary it is applied to o1.// If op is binary it is applied to o1 and o2.// The result of the application is returned.char apply(char o1, char op, char o2='0'){ assert(o1 == '0' || o1 == '1'); assert(o2 == '0' || o2 == '1'); int v1 = o1 - '0'; int v2 = o2 - '0'; int v = op == '!' ? !v1 : op == '&' ? v1&v2 : op == '|' ? v1|v2 : op == '-' ? (!v1)|v2 : op == '<' ? !(v1^v2) : 2; assert (v == 0 || v == 1); return '0' + v;}// The proposition symbols occuring in s are given numbers in alphabetical order.// The resulting mapping is returned.mci symbols(string &s){ mci m; for (unsigned int i=0 ; i<s.size() ; i++) if (islower(s[i])) m[s[i]] = 1; int bit = 0; // The map m is traversed in reverse alphabetic order. // Thus, the last proposition symbol will be represented by the least significant bit 0. for (mci::reverse_iterator it = m.rbegin() ; it != m.rend() ; ++it) it->second = bit++; return m;}// The positions of all proposition symbols, operators and brackets occuring in s are identified.// Grouped with their positions, these entities are inserted into a queue that is returned.qi lex(string &s){ qi q; for (unsigned int i=0 ; i<s.size() ; i++) if (islower(s[i]) || s[i] == '!' || s[i] == '&' || s[i] == '|' || s[i] == '(' || s[i] == ')') q.push(i); else if (s[i] == '-' || s[i] == '<') { // Implication and equivalence are represented by three-character symbols. // We use the first symbol, but the position of the second (center) character. char ch = s[i]; for (i++ ; i<s.size() && s[i] != '-' ; i++) assert(s[i] == ' '); // This is a hack: the second (center) character is overwritten by the first symbol. s[i] = ch; q.push(i); for (i++ ; i<s.size() && s[i] != '>' ; i++) assert(s[i] == ' '); assert(i<s.size()); } else assert(s[i] == ' '); return q;}// The queue q containing the essence of the input is parsed into a syntax tree.// The tree is represented by the arrays v1 and v2 containing the positions of the children of each node.// The nodes are indexed by integers, and the root is returned.int parse(string &s, qi &q, vi &v1, vi &v2){ si st; while (!q.empty()) { int next = q.front(); q.pop(); if (s[next] == ')') { // The top of the stack now contains the operator and its operands. // The operator is on the next-to-top position. // If it is unary, its operand is on the top position. // If it is binary, its first operand is on the 3rd position and its second operand is on the top. int o2 = st.top(); st.pop(); int op = st.top(); st.pop(); if (s[op] == '!') v1[op] = o2; else { assert(binary(s[op])); v2[op] = o2; int o1 = st.top(); st.pop(); v1[op] = o1; } // The matching bracket must be removed. assert(s[st.top()] == '('); st.pop(); st.push(op); } else st.push(next); } // The top of the one-element stack contains the index of the root of the syntax tree. assert(st.size() == 1); return st.top();}// The tree represented by v1 and v2 and rooted at node is evaluated.// The mapping m gives the bit-position in the counter q for each proposition symbol, and thereby its value.// The string s is overwritten such that the position of each sub-tree contains its value.void eval(string &s, int node, vi &v1, vi &v2, mci &m, int q){ if (islower(s[node])) s[node] = q & (1 << m[s[node]]) ? '1' : '0'; else if (s[node] == '!') { // The unary node is evaluated recursively. eval(s, v1[node], v1, v2, m, q); s[node] = apply(s[v1[node]], s[node]); } else { // The binary node is evaluated recursively. assert(binary(s[node])); eval(s, v1[node], v1, v2, m, q); eval(s, v2[node], v1, v2, m, q); s[node] = apply(s[v1[node]], s[node], s[v2[node]]); }}// A truth table is created for the string line, its syntax tree is represented by v1 and v2 and rooted at node.// The mapping m gives the bit-position for each proposition symbol.void truthtable(string &line, int root, vi &v1, vi &v2, mci &m){ int qmax = 1 << m.size(); for (int q=0 ; q<qmax ; q++) { // The value of q represents one line of the table by the corresponding assignment. string s = line; eval(s, root, v1, v2, m, q); // The post-processing removes the brackets and superfluous characters of three-character operators. for (unsigned int i=0 ; i<s.size() ; i++) if (s[i] != '0' && s[i] != '1') s[i] = ' '; cout << s << endl; }}int main(){ string line; while (getline(in, line)) { cout << line << endl; mci m = symbols(line); qi q = lex(line); vi v1(line.size()); vi v2(line.size()); int root = parse(line, q, v1, v2); truthtable(line, root, v1, v2, m); cout << endl; } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -