最近用python实现了真值表,经过有点儿曲折,刚开始没考虑优先级,直到前天才发现这个问题(离散数学没学好啊),用栈改了一下。话说python就是强,把列表类型当栈用,直接调用列表的pop()和append()非常方便,废话少说上代码(命令行版)。

  1. 首先是导入外部库和定义函数

    1. #导入正则表达式re库,用来从字符串中提取信息
    2. import re
    3. #prettytable库帮我们打印出漂亮的表格
    4. from prettytable import PrettyTable
    5.  
    6. #过滤掉(
    7. def filter_brackets(string):
    8. p=re.compile(r'[(]+(.*)')
    9. return(p.findall(string)[0])
    10.  
    11. #判断格式是否合理,并返回真值表的列名
    12. def to_show(string):
    13. #利用patten提取括号中的内容
    14. patten=re.compile(r'[(](.*?)[)]')
    15. contents_in_brackets=patten.findall(string)
    16. #contents_in_brackets中的元素存在'('的现象,故对所有元素进行遍历过滤掉这些括号
    17. for i in range(len(contents_in_brackets)):
    18. if contents_in_brackets[i].startswith('('):
    19. contents_in_brackets[i]=filter_brackets(contents_in_brackets[i])
    20.  
    21. #利用sp提取命题变元,n为命题变元的个数
    22. sp=re.compile('[a-zA-Z]')
    23. simple_exp=sp.findall(string)
    24.  
    25. l=simple_exp+contents_in_brackets
    26. #l去重得到l1
    27. l1=[]
    28. for i in l:
    29. if i not in l1:
    30. l1.append(i)
    31. l1.append(string)
    32. l1.sort(key=len)
    33. #第一项是要展示的部分,第二项是命题变元(有重复)
    34. return([l1,simple_exp])
  2. 其次是运算部分
    1. def get_prioty(operator):
    2. #if operator=='(' or operator==')'
    3. p=-1
    4. if operator=='(':
    5. p=6
    6. elif operator=='!':
    7. p=5
    8. elif operator=='&':
    9. p=4
    10. elif operator=='#':
    11. p=3
    12. elif operator=='|':
    13. p=2
    14. elif operator=='>':
    15. p=1
    16. elif operator=='=':
    17. p=0
    18. return(p)
    19.  
    20. #两命题变元运算
    21. def cal(a,operator,b=-1):
    22. if operator == '!':
    23. boo = not a
    24. elif operator == '&':
    25. boo = a and b
    26. elif operator == '|':
    27. boo = a or b
    28. #异或
    29. elif operator == '#':
    30. boo = (a and (not b)) or ((b and (not a)))
    31. #条件(注意顺序是反的)
    32. elif operator == '>':
    33. boo = (not b) or a
    34. #等值
    35. elif operator == '=':
    36. boo = ((not a) and (not b)) or (a and b)
    37. else:
    38. print("there is no such operator")
    39. return(None)
    40. if(boo):
    41. return(1)
    42. else:
    43. return(0)
    44.  
    45. #对传入的字符串进行运算(传入的字符串无括号),且
    46. def cal_str(Str,dic):
    47. i=0
    48. #s0为数字栈
    49. s0=[]
    50. #s1为运算符栈
    51. s1=[]
    52. while i<len(Str) or len(s1)!=0:
    53. if i<len(Str):
    54. c=Str[i]
    55. else:
    56. c=''
    57. if c.isalpha():
    58. s0.append(dic[c])
    59. i=i+1
    60. else:
    61. if len(s1)==0 or (c!=')' and s1[-1]=='(') or get_prioty(c)>=get_prioty(s1[-1]):
    62. s1.append(c)
    63. i=i+1
    64. continue
    65.  
    66. if c==')' and s1[-1]=='(':
    67. s1.pop()
    68. i=i+1
    69. continue
    70.  
    71. if (i>=len(Str) and len(s1)!=0) or (c==')' and s1[-1]!='(') or get_prioty(c)<=get_prioty(s1[-1]):
    72. opt=s1.pop()
    73. if opt!='!':
    74. result=cal(s0.pop(),opt,s0.pop())
    75. elif opt=='!':
    76. result=cal(s0.pop(),opt)
    77. s0.append(result)
    78. return(s0[0])
  3. 利用bin()函数得到相应元素个数的全部真值赋值,经过一顿操作使用zip()函数将命题变元与其真值(0或1)绑定起来,遍历所有的真值赋值情况,计算每种真值情况下的各个表达式的值,得到真值表
    1. #产生真值序列(字典形式)的列表
    2. def gen_truth_list(elems):
    3. num=len(elems)
    4. tl=[]
    5. for i in range(2**num):
    6. st=bin(i)[2:].zfill(num)
    7. truth_list=list(map(lambda j:int(j),list(st)))
    8. #append:将字典以整体形式加到列表中
    9. tl.append(dict(zip(elems,truth_list)))
    10. return(tl)
    11.  
    12. def gen_all_line(truth_list,header):
    13. #产生真值表数据
    14. all_line=[]
    15. for line_truth in truth_list:
    16. per_line=[]
    17. for exp in header:
    18. truth=cal_str(exp,line_truth)
    19. per_line.append(truth)
    20. all_line.append(per_line)
    21. return(all_line)
  4. 根据真值表获得主范式
    1. #返回一个小项
    2. def get_minterm(term):
    3. if len(term)!=0:
    4. return('('+'&'.join(term)+')')
    5. else:
    6. return('')
    7.  
    8. #返回一个大项
    9. def get_maxterm(term):
    10. if len(term)!=0:
    11. return('('+'|'.join(term)+')')
    12. else:
    13. return('')
    14.  
    15. def get_dnf(header,elems):
    16. truth_list=gen_truth_list(elems)
    17. minterms=[]
    18. all_line=gen_all_line(truth_list,header)
    19. #遍历每一行
    20. for line_id in range(2**len(elems)):
    21. #term为包含某小项中各命题变元正确形式的列表
    22. term=[]
    23. #如果该行的真值赋值使得表达式为1
    24. if all_line[line_id][-1]==1:
    25. #遍历该行对应的真值赋值
    26. for t in truth_list[line_id]:
    27. if truth_list[line_id][t]==1:
    28. term.append(t)
    29. else:
    30. term.append('!'+t)
    31. #表达式为1才能加入小项列表
    32. minterm=get_minterm(term)
    33. if minterm!='':
    34. minterms.append(minterm)
    35. return('|'.join(minterms))
    36.  
    37. def get_cnf(header,elems):
    38. truth_list=gen_truth_list(elems)
    39. maxterms=[]
    40. all_line=gen_all_line(truth_list,header)
    41. #遍历每一行
    42. for line_id in range(2**len(elems)):
    43. term=[]
    44. #如果该行的真值赋值使得表达式为0
    45. if all_line[line_id][-1]==0:
    46. #遍历该行对应的真值赋值
    47. for t in truth_list[line_id]:
    48. if truth_list[line_id][t]==0:
    49. term.append(t)
    50. else:
    51. term.append('!'+t)
    52. #表达式为1才能加入小项列表
    53. maxterm=get_maxterm(term)
    54. if maxterm!='':
    55. maxterms.append(maxterm)
    56. return('&'.join(maxterms))
  5. 主函数如下
    1. if __name__=="__main__":
    2. #获取字符串
    3. string=input('input:')
    4.  
    5. header=to_show(string)[0]
    6. elem=to_show(string)[1]
    7. elems=[]
    8. for i in elem:
    9. if i not in elems:
    10. elems.append(i)
    11. truth_list=gen_truth_list(elems)
    12.  
    13. all_line=[]
    14. for line_truth in truth_list:
    15. per_line=[]
    16. for exp in header:
    17. truth=cal_str(exp,line_truth)
    18. per_line.append(truth)
    19. all_line.append(per_line)
    20.  
    21. truth_table=PrettyTable(header)
    22. for line in all_line:
    23. truth_table.add_row(line)
    24.  
    25. print('The truth table of this formula is printed below:')
    26. print(truth_table)
    27.  
    28. continue_or_not=input('Show "principal disjunctive normal form" \n or "principal conjunctive normal form"? [y/n]\n')
    29. #继续输出主范式
    30. if continue_or_not=='y':
    31. print('pdnf(主析取范式): '+get_dnf(header,elems))
    32. print('pcnf(主合取范式): '+get_cnf(header,elems))

    第一次写技术博客,有点儿激动,先写到这,过两天给出一个GUI版本的。

离散数学——python实现真值表和打印主范式的更多相关文章

  1. 使用python编写量子线路打印的简单项目,并使用Sphinx自动化生成API文档

    技术背景 该文章一方面从量子线路的打印着手,介绍了一个简单的python量子线路工程.同时基于这个简单的小工程,我们顺带的介绍了python的API文档自动化生成工具Sphinx的基本使用方法. 量子 ...

  2. Python For嵌套循环 图形打印X型 nested loop -练习题

    For嵌套循环图形打印作业很多是C++语言做的,我觉得Python应该也能做,就来试一试. 原网址C++练习题:http://www.imooc.com/qadetail/216848?t=33880 ...

  3. Python 九九乘法表打印

    Python 九九乘法表打印 小练习 for i in range(1,10,1): for j in range(1,i+1): print("%s*%s=%s" %(j,i,i ...

  4. Python For嵌套循环 图形打印X型 nested loop - 练习题答案

    上一篇:Python For嵌套循环 图形打印X型 nested loop - 练习题 上一篇留的Python For嵌套循环 图形打印X型练习题的答案. 由于网上很多嵌套循环都是C++语言写的,用P ...

  5. python 多线程实现循环打印 abc

    python 多线程实现循环打印 abc 好久没写过python了, 想自己实践一下把 非阻塞版 import threading import time def print_a(): global ...

  6. Python练习题 018:打印星号菱形

    [Python练习题 018] 打印出如下图案(菱形): * *** ***** ******* ***** *** * --------------------------------------- ...

  7. Python输入一个数字打印等腰三角形

    要求 用户输入一个数字,按照数字打印出等腰三角形 思路 1,用户输入的数字为n代表一共有多少行 2,使用一个循环带两个for循环,第一层循环是循环行数,第二层两个平行for循环一个打印空格一个打印*号 ...

  8. Windows 10安装Python 3 7成功打印Hello World!

    Python下载 Python最新源码,二进制文档,新闻资讯等可以在Python的官网查看到: Python官网:https://www.python.org/ 你可以在以下链接中下载 Python ...

  9. Python 3 进阶 —— print 打印和输出

    在 Python 中,print 可以打印所有变量数据,包括自定义类型. 在 2.x 版本中,print 是个语句,但在 3.x 中却是个内置函数,并且拥有更丰富的功能. 参数选项 可以用 help( ...

随机推荐

  1. IDEA-Eclipse结构项目转移到 Idea教程

    1.确定Idea的svn配置 2.从svn导出项目 3.检出项目完成,开始设置 4.配置完成,设置svn忽略文件,忽略掉idea配置文件等 5. 设置完毕

  2. C++中抽象类和多继承

    C++中没有java中接口的概念,但是可以使用抽象类来模拟java中的接口. 工程上的多继承 工程开发中的多继承几乎是不被使用的 多继承带来的代码的复杂性,远远大于其代码带来的便利性. 多继承对代码的 ...

  3. PPAS数据库备份与恢复

    PPAS数据库备份不同于普通的Postgresql数据库的备份,因为PPAS数据库是兼容Oracle数据库的,所以会涉及到同义词.包.存储过程等,这个时候用Postgresql社区的备份与恢复工具时, ...

  4. [Codeforces 204E] Little Elephant and Strings

    [题目链接] https://codeforces.com/contest/204/problem/E [算法] 首先构建广义后缀自动机 对于自动机上的每个节点 , 维护一棵平衡树存储所有它所匹配的字 ...

  5. rsync 端口更换(默认873)

    一般使用默认端口的话, 在服务端的启动命令为: /usr/bin/rsync --address=192.168.1.23 --daemon 如果在客户端需要换另外的端口侦听, 则使用 /usr/bi ...

  6. Java中“分号”引起的陷阱

    对于这类问题而言,难度不大,多半是由于我们有误操作引起的.但在查找问题所在的时候我们有可能需要花费一番功夫了. 实例一: package com.yonyou.test; /** * 测试类 * @a ...

  7. bzoj2118

    最短路 很早以前做的了 数据范围太大,不能直接算 mn=min(a[i]) 算出d[i]表示sum%mn=i最小能构成的数,这个用最短路就行了,然后计算d[i],d[i]+mn的个数统计答案 #inc ...

  8. Python-连接Redis并操作

    首先开启redis的外连 sch01ar@ubuntu:~$ sudo vim /etc/redis/redis.conf 把bind 127.0.0.1这行注释掉 然后重启redis sudo /e ...

  9. CCNet说明文档

    1.CCNet安装步骤 1)    安装CCNet服务器端:CruiseControl.NET-1.8.5.0-Setup.exe 2)    安装CCNet客户端:CruiseControl.NET ...

  10. Spring MVC Flash Attribute 的讲解与使用示例

    转自:https://www.oschina.net/translate/spring-mvc-flash-attribute-example Spring MVC 3.1版本加了一个很有用的特性,F ...