离散数学——python实现真值表和打印主范式
最近用python实现了真值表,经过有点儿曲折,刚开始没考虑优先级,直到前天才发现这个问题(离散数学没学好啊),用栈改了一下。话说python就是强,把列表类型当栈用,直接调用列表的pop()和append()非常方便,废话少说上代码(命令行版)。
- 首先是导入外部库和定义函数
#导入正则表达式re库,用来从字符串中提取信息
import re
#prettytable库帮我们打印出漂亮的表格
from prettytable import PrettyTable #过滤掉(
def filter_brackets(string):
p=re.compile(r'[(]+(.*)')
return(p.findall(string)[0]) #判断格式是否合理,并返回真值表的列名
def to_show(string):
#利用patten提取括号中的内容
patten=re.compile(r'[(](.*?)[)]')
contents_in_brackets=patten.findall(string)
#contents_in_brackets中的元素存在'('的现象,故对所有元素进行遍历过滤掉这些括号
for i in range(len(contents_in_brackets)):
if contents_in_brackets[i].startswith('('):
contents_in_brackets[i]=filter_brackets(contents_in_brackets[i]) #利用sp提取命题变元,n为命题变元的个数
sp=re.compile('[a-zA-Z]')
simple_exp=sp.findall(string) l=simple_exp+contents_in_brackets
#l去重得到l1
l1=[]
for i in l:
if i not in l1:
l1.append(i)
l1.append(string)
l1.sort(key=len)
#第一项是要展示的部分,第二项是命题变元(有重复)
return([l1,simple_exp]) - 其次是运算部分
def get_prioty(operator):
#if operator=='(' or operator==')'
p=-1
if operator=='(':
p=6
elif operator=='!':
p=5
elif operator=='&':
p=4
elif operator=='#':
p=3
elif operator=='|':
p=2
elif operator=='>':
p=1
elif operator=='=':
p=0
return(p) #两命题变元运算
def cal(a,operator,b=-1):
if operator == '!':
boo = not a
elif operator == '&':
boo = a and b
elif operator == '|':
boo = a or b
#异或
elif operator == '#':
boo = (a and (not b)) or ((b and (not a)))
#条件(注意顺序是反的)
elif operator == '>':
boo = (not b) or a
#等值
elif operator == '=':
boo = ((not a) and (not b)) or (a and b)
else:
print("there is no such operator")
return(None)
if(boo):
return(1)
else:
return(0) #对传入的字符串进行运算(传入的字符串无括号),且
def cal_str(Str,dic):
i=0
#s0为数字栈
s0=[]
#s1为运算符栈
s1=[]
while i<len(Str) or len(s1)!=0:
if i<len(Str):
c=Str[i]
else:
c=''
if c.isalpha():
s0.append(dic[c])
i=i+1
else:
if len(s1)==0 or (c!=')' and s1[-1]=='(') or get_prioty(c)>=get_prioty(s1[-1]):
s1.append(c)
i=i+1
continue if c==')' and s1[-1]=='(':
s1.pop()
i=i+1
continue if (i>=len(Str) and len(s1)!=0) or (c==')' and s1[-1]!='(') or get_prioty(c)<=get_prioty(s1[-1]):
opt=s1.pop()
if opt!='!':
result=cal(s0.pop(),opt,s0.pop())
elif opt=='!':
result=cal(s0.pop(),opt)
s0.append(result)
return(s0[0]) - 利用bin()函数得到相应元素个数的全部真值赋值,经过一顿操作使用zip()函数将命题变元与其真值(0或1)绑定起来,遍历所有的真值赋值情况,计算每种真值情况下的各个表达式的值,得到真值表
#产生真值序列(字典形式)的列表
def gen_truth_list(elems):
num=len(elems)
tl=[]
for i in range(2**num):
st=bin(i)[2:].zfill(num)
truth_list=list(map(lambda j:int(j),list(st)))
#append:将字典以整体形式加到列表中
tl.append(dict(zip(elems,truth_list)))
return(tl) def gen_all_line(truth_list,header):
#产生真值表数据
all_line=[]
for line_truth in truth_list:
per_line=[]
for exp in header:
truth=cal_str(exp,line_truth)
per_line.append(truth)
all_line.append(per_line)
return(all_line) - 根据真值表获得主范式
#返回一个小项
def get_minterm(term):
if len(term)!=0:
return('('+'&'.join(term)+')')
else:
return('') #返回一个大项
def get_maxterm(term):
if len(term)!=0:
return('('+'|'.join(term)+')')
else:
return('') def get_dnf(header,elems):
truth_list=gen_truth_list(elems)
minterms=[]
all_line=gen_all_line(truth_list,header)
#遍历每一行
for line_id in range(2**len(elems)):
#term为包含某小项中各命题变元正确形式的列表
term=[]
#如果该行的真值赋值使得表达式为1
if all_line[line_id][-1]==1:
#遍历该行对应的真值赋值
for t in truth_list[line_id]:
if truth_list[line_id][t]==1:
term.append(t)
else:
term.append('!'+t)
#表达式为1才能加入小项列表
minterm=get_minterm(term)
if minterm!='':
minterms.append(minterm)
return('|'.join(minterms)) def get_cnf(header,elems):
truth_list=gen_truth_list(elems)
maxterms=[]
all_line=gen_all_line(truth_list,header)
#遍历每一行
for line_id in range(2**len(elems)):
term=[]
#如果该行的真值赋值使得表达式为0
if all_line[line_id][-1]==0:
#遍历该行对应的真值赋值
for t in truth_list[line_id]:
if truth_list[line_id][t]==0:
term.append(t)
else:
term.append('!'+t)
#表达式为1才能加入小项列表
maxterm=get_maxterm(term)
if maxterm!='':
maxterms.append(maxterm)
return('&'.join(maxterms)) - 主函数如下
if __name__=="__main__":
#获取字符串
string=input('input:') header=to_show(string)[0]
elem=to_show(string)[1]
elems=[]
for i in elem:
if i not in elems:
elems.append(i)
truth_list=gen_truth_list(elems) all_line=[]
for line_truth in truth_list:
per_line=[]
for exp in header:
truth=cal_str(exp,line_truth)
per_line.append(truth)
all_line.append(per_line) truth_table=PrettyTable(header)
for line in all_line:
truth_table.add_row(line) print('The truth table of this formula is printed below:')
print(truth_table) continue_or_not=input('Show "principal disjunctive normal form" \n or "principal conjunctive normal form"? [y/n]\n')
#继续输出主范式
if continue_or_not=='y':
print('pdnf(主析取范式): '+get_dnf(header,elems))
print('pcnf(主合取范式): '+get_cnf(header,elems))第一次写技术博客,有点儿激动,先写到这,过两天给出一个GUI版本的。
离散数学——python实现真值表和打印主范式的更多相关文章
- 使用python编写量子线路打印的简单项目,并使用Sphinx自动化生成API文档
技术背景 该文章一方面从量子线路的打印着手,介绍了一个简单的python量子线路工程.同时基于这个简单的小工程,我们顺带的介绍了python的API文档自动化生成工具Sphinx的基本使用方法. 量子 ...
- Python For嵌套循环 图形打印X型 nested loop -练习题
For嵌套循环图形打印作业很多是C++语言做的,我觉得Python应该也能做,就来试一试. 原网址C++练习题:http://www.imooc.com/qadetail/216848?t=33880 ...
- Python 九九乘法表打印
Python 九九乘法表打印 小练习 for i in range(1,10,1): for j in range(1,i+1): print("%s*%s=%s" %(j,i,i ...
- Python For嵌套循环 图形打印X型 nested loop - 练习题答案
上一篇:Python For嵌套循环 图形打印X型 nested loop - 练习题 上一篇留的Python For嵌套循环 图形打印X型练习题的答案. 由于网上很多嵌套循环都是C++语言写的,用P ...
- python 多线程实现循环打印 abc
python 多线程实现循环打印 abc 好久没写过python了, 想自己实践一下把 非阻塞版 import threading import time def print_a(): global ...
- Python练习题 018:打印星号菱形
[Python练习题 018] 打印出如下图案(菱形): * *** ***** ******* ***** *** * --------------------------------------- ...
- Python输入一个数字打印等腰三角形
要求 用户输入一个数字,按照数字打印出等腰三角形 思路 1,用户输入的数字为n代表一共有多少行 2,使用一个循环带两个for循环,第一层循环是循环行数,第二层两个平行for循环一个打印空格一个打印*号 ...
- Windows 10安装Python 3 7成功打印Hello World!
Python下载 Python最新源码,二进制文档,新闻资讯等可以在Python的官网查看到: Python官网:https://www.python.org/ 你可以在以下链接中下载 Python ...
- Python 3 进阶 —— print 打印和输出
在 Python 中,print 可以打印所有变量数据,包括自定义类型. 在 2.x 版本中,print 是个语句,但在 3.x 中却是个内置函数,并且拥有更丰富的功能. 参数选项 可以用 help( ...
随机推荐
- Python 爬虫 —— 文件及文件夹操作
0. 文件名.路径信息.拓展名等 #取文件后缀 >>> os.path.splitext("/root/a.py") ('/root/a', '.py') #取目 ...
- PLSQL查询最近编绎、创建、修改过的过程函数
SELECT * FROM User_Objects t WHERE t.Object_Type IN ('PROCEDURE', 'PACKAGE BODY', 'FUNCTION') AND t. ...
- bzoj 1007: [HNOI2008]水平可见直线 半平面交
题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=1007; 题解 其实就是求每条直线的上半部分的交 所以做裸半平面交即可 #include ...
- 【LeetCode】084. Largest Rectangle in Histogram
题目: Given n non-negative integers representing the histogram's bar height where the width of each ba ...
- TVYJ1266:费解的开关
我对状态空间的理解:https://www.cnblogs.com/AKMer/p/9622590.html 题目传送门:http://www.joyoi.cn/problem/tyvj-1266 这 ...
- java中的设计模式及其六大原则
设计模式分类: 一共分为3大类:创造型模式.结构型模式.行为型模式. 创造型模式:工厂方法(FactoryMethod).抽象工厂模式(AbstractFactory).建造者模式(Builder). ...
- MyEclipse 手动安装Velocity 编辑器
最近项目有使用Velocity 模板引擎,从而会用到*.VM页面!Myeclipse打开VM页面字体一片漆黑,哪有JSP那样看起来舒服(个人感觉)!为了解决这一问题就要安装Velocity编辑器,安装 ...
- Python函数式编程(把函数作为参数传入)
map:接受两个参数(函数,Iterable),map将传入的函数依次作用于Iterable的每个元素,并且返回新的Iterable def f(x): return x*x r = map(f,[1 ...
- jquery插件开发常用总结一
由于使用jquery插件后当form表单提交的时候,若发生错误,同时有验证错误文本时,即使用rules和message后,会自动生成一个label标签里面装有错误文件值. 我们可以替换它: 方式为:v ...
- SpringMvc之参数绑定注解详解之三
2. @RequestHeader.@CookieValue @RequestHeader 注解,可以把Request请求header部分的值绑定到方法的参数上. 示例代码: 这是一个Request ...