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

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

    #导入正则表达式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])
  2. 其次是运算部分
    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])
  3. 利用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)
  4. 根据真值表获得主范式
    #返回一个小项
    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))
  5. 主函数如下
    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实现真值表和打印主范式的更多相关文章

  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. 利用perlin noise 生成 wood texture

    %%% Perlin Noise %%% Wood_texture clc; clear all; close all; addpath('E:\PhotoShop Algortihm\Image P ...

  2. fswebcam 获取图片

    /************************************************************************* * fswebcam 获取图片 * 说明: * 通 ...

  3. netsh wlan start hostednetwork

    常用的无线网命令: 一.开启系统承载网络模块和新建无线网络命令: netsh wlan set hostednetwork mode=allow ssid=wifi key=12345678说明:ss ...

  4. Poj 3356 ACGT(LCS 或 带备忘的递归)

    题意:把一个字符串通过增.删.改三种操作变成另外一个字符串,求最少的操作数. 分析: 可以用LCS求出最大公共子序列,再把两个串中更长的那一串中不是公共子序列的部分删除. 分析可知两个字符串的距离肯定 ...

  5. hibernate 数据关联一对多

    一对多,多对一 (在多的一端存放一的外键) 但是在实体类中不需要创建这个外键 // 在一的一方创建Set集合 public class User { private Integer id; priva ...

  6. stm32之内部功能

    本文将提到以下内容: 位带操作 中断 printf重定向 随机数发生器RNG AD/DA DMA 高性能计算能力 加密 ART加速 一.位带操作 在学习51单片机的时候就使用过位操作,通过关键字sbi ...

  7. 可定制的分词库——Yaha(哑哈)分词

    可定制的分词库——Yaha(哑哈)分词在线测试地址:http://yaha.v-find.com/ 部署于GAE yahademo.appspot.comYaha分词主要特点是把分词过程分成了4个阶段 ...

  8. 很随意的让你了解 - 最小生成树之Prim算法

    首先分成两个容器. 第一个容器就是装有生成树里面的顶点,第二个容器就是装有没有放入这个第一个容器中的顶点. 首先默认往第一个容器里面装一个顶点.然后..计算出第二个容器里所有顶点和这个顶点的距离.没有 ...

  9. Python及R安装包版本查看方法

    R包查询 查询已安装的所有的包:library() 或installed.packages()(括号内为空,区别以上两项) 查询具体包的信息: help(package="pheatmap& ...

  10. (分享)一位资深程序员大牛给予Java初学者的学习路线建议

    摘自:http://bbs.itheima.com/thread-333038-1-1.html 如果你是在校学生,务必要在学好基础(比如计算机系统.算法.编译原理等等)的前提下,再考虑去进行下面的学 ...