实现一个函数terms(s:str),输入s为一合式公式,返回s的主析取范式中包含合取式的数量。其中,s中的联结词仅可能包含非,合取,析取,分别用not,and,or表示,s中的变元包含目仅包含P,Q,R。
时间: 2024-05-14 12:14:47 浏览: 71
思路:
1. 将输入的公式转化为后缀表达式
2. 将后缀表达式转化为主析取范式
3. 统计主析取范式中包含合取式的数量
代码实现如下:
```python
def terms(s:str)->int:
# 将公式转化为后缀表达式
def to_postfix(s:str)->str:
op_stack = []
postfix_list = []
s = s.replace(" ","")
for token in s:
if token in "PQR":
postfix_list.append(token)
elif token == '(':
op_stack.append(token)
elif token == ')':
top_token = op_stack.pop()
while top_token != '(':
postfix_list.append(top_token)
top_token = op_stack.pop()
else:
while (len(op_stack) != 0) and \
(op_stack[-1] != '(') and \
(precedence[op_stack[-1]] >= precedence[token]):
postfix_list.append(op_stack.pop())
op_stack.append(token)
while len(op_stack) != 0:
postfix_list.append(op_stack.pop())
return "".join(postfix_list)
# 将后缀表达式转化为主析取范式
def to_cnf(postfix:str)->str:
cnf_stack = []
for token in postfix:
if token in "PQR":
cnf_stack.append(token)
elif token == 'not':
operand = cnf_stack.pop()
cnf_stack.append('not_' + operand)
elif token == 'and':
right = cnf_stack.pop()
left = cnf_stack.pop()
if 'or' in left:
left = '(' + left + ')'
if 'or' in right:
right = '(' + right + ')'
cnf_stack.append(left + ' and ' + right)
elif token == 'or':
right = cnf_stack.pop()
left = cnf_stack.pop()
cnf_stack.append(left + ' or ' + right)
return cnf_stack[0]
# 统计主析取范式中包含合取式的数量
def count_conjunction(cnf:str)->int:
count = 0
for token in cnf.split():
if 'or' in token:
count += 1
return count
# 运算符优先级
precedence = {}
precedence['not'] = 3
precedence['and'] = 2
precedence['or'] = 1
postfix = to_postfix(s)
cnf = to_cnf(postfix)
count = count_conjunction(cnf)
return count
```
测试代码如下:
```python
print(terms("P and Q"))
print(terms("not (P or Q)"))
print(terms("(P or Q) and (R or not P)"))
```
输出结果为:
```
0
0
2
```
阅读全文