python - 根据表达式打印真值表
输入逻辑表达式,输出真值表,支持六个基本逻辑运算
最终效果:
输入合适公式(没有考虑优先级,只根据括号优先),输出时会提取其中的元素(比如这里有A B C),并打印真值表。
算法思路:
求值的一般顺序是:带入每个元素的值,求出式子的真值,所以可以分为两块:1.枚举元素值(枚举) 2.根据元素值求式子值(计算)
我认为这个的难点在于枚举,我们既要想办法提取出每一个元素,又要为其赋值(0和1)
我们先约定好六个运算符
'''
否.......... !(非)
合取........ &(与)
可兼或...... |(或)
不可兼或.... #
由...可得... >
当且仅当.... =
'''
并封装好这个真值表打印器
class FindTruth:'''构造函数'''def __init__(self):'''输入'''def __In(self):'''枚举'''def __Count(self, i):'''计算公式结果'''def __Sum(self, Str):'''配对左右括号'''def __Pei(self, cur, Str):'''运算操作符'''def __Add(self, w, a, b = -1):'''输出'''def __Out(self):
一,首先处理枚举:
对于提取元素:涉及到字符串的处理以及查重,python提供了便捷的set集合来处理
对于赋值:比如式子A|B|C,提取出ABC后,一共有从000 到 111,2^3种情况,而N个元素就有2^N种情况,显然是不能用简单的循环是实现的,这里可以用递归来处理
a.利用set提取元素
set(字符串)能把字符串里每个字符提取出来,构成一个集合,而集合是不存在相同字符的,所以这里完成了筛选重复字符的工作。
如set('A|B&C') = {'A', 'B', 'C', '|', '&'}
seta.difference(setb)能让seta留下于setb集合中不同的元素。
所以第二句生成了一个筛选掉运算符的元素集合,完成了元素的提取
def __In(self):#得到表达式Strself.Str = input("input your expression: \n")#筛出字母集合self.Set = set(self.Str).difference(set("()!&|>=#"))
b.利用递归枚举赋值
如何递归呢,这里假如有三个元素A,B,C
递归函数有一个参数 i ,用来指定此次因该枚举哪一个元素的值,比如 i = 0, 则枚举A的值。
首先初始化一个字典用来存储元素的值:self.dict = {'A':0, 'B':0, 'C': 0}
第一次:{'A':0, 'B':0, 'C': 0},i = 1,所以先分别给A赋值0和赋值1,并把 i 加一,再调用枚举函数(也就是递归调用自己)。因为要调用自己两次,这里就产生了1*2 = 2个分支:
分支1:{'A':0, 'B':0, 'C': 0},i = 1
分支2:{'A':1, 'B':0, 'C': 0},i = 1
第二次,i = 1,分别给B赋值0和1,在第一次的两个分支的基础上产生了2*2 = 4个分支
分支1:{'A':0, 'B':0, 'C': 0},i = 1
分支11:{'A':0, 'B':0, 'C': 0},i = 2
分支12:{'A':0, 'B':1, 'C': 0},i = 2
分支2:{'A':1, 'B':0, 'C': 0},i = 1
分支21:{'A':1, 'B':0, 'C': 0},i = 2
分支22:{'A':1, 'B':1, 'C': 0},i = 2
第三次,同理,给C赋值的时候,会产生总共4*2 = 8个分支,这时候递归枚举也结束了,我们也得到了八个枚举的结果
A B C
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
实现代码:
def __Count(self, i):'''结束条件:若最后一个元素也完成了枚举,则 打印 + 运算 '''if i == len(self.Lis):S = ''for l in self.Lis:S = S + str(self.Dic[l]) + ' 'print(S,self.__Sum(self.Str))#调用self__Sum()函数进行运算return'''不是结尾,则赋值并调用自己,产生两个分支'''self.Dic[self.Lis[i]] = 0self.__Count(i+1)self.Dic[self.Lis[i]] = 1self.__Count(i+1)
二,再来处理计算 __Sum(self, Str)
计算的思路很简单,我们分别设置三个值:
s :用来存储当前的终值,初始值设置为-1
s0 :用来存储当前式子或元素的值
operater :用来存储目前的操作符
然后一个字符一个字符地循环遍历表达式:
例:str = 'A | (A & B) & C' 调用 __sum(self, str):
循环1:字符 = 'A",则s = A的值
循环2:字符 = '|',则operater = '|'
循环3:字符 = '(',则s0 = __sum(self, ’括号内的那坨表达式‘),(这样便可利用递归简单地完成括号的处理)
s = (s operator s0),s0 = -1(更新s的值)
.......
到最后一个字符结束后,式子的值已经存储于s中了。
实现代码:
#求公式结果
def __Sum(self, Str):i = 0 #字符位置s = -1#式子真值while i < len(Str):c = Str[i]#单操作符'!'要做特殊的分类处理if c == "!":#右边是字母if Str[i+1] in self.Set:c = Str[i+1]i = i + 1s0 = self.__Add('!',self.Dic[c]) #右边是左括号else:end = self.__Pei(i+1, Str)s0 = self.__Add('!', self.__Sum(Str[i+1:end+1]))i = end#字母elif c in self.Set:s0 = self.Dic[c]#其它运算符elif c in set("&|>=#"):operat = c#左括号elif c == '(':end = self.__Pei(i, Str)s0 = self.__Sum(Str[i+1:end])i = end#运算结果if s == -1:s = s0s0 = -1elif operat != 0 and s0 != -1:s1 = ss = self.__Add(operat, s, s0)operat = 0s0 = -1i = i + 1return s
#配对左右括号
def __Pei(self, cur, Str):kflag = 1 # 左括号的数目while not kflag == 0:cur = cur + 1if Str[cur] == '(':kflag = kflag + 1elif Str[cur] == ')':kflag = kflag - 1return cur
#运算操作
def __Add(self, operator, a, b = -1):#b默认为-1时,表示是单操作符号' ! 'if operator == '!':boo = not aelif operator == '&':boo = a and belif operator == '|':boo = a or belif operator == '#':boo = ((not a) or (not b)) and (a or b)elif operator == '>':boo = (not a) or belif operator == '=':boo = ((not a) and (not b)) or (a and b)else:print("there is no such operator")if boo:return 1else:return 0
完整代码:
# -*- coding: utf-8 -*-
'''
否.......... !
合取........ &
可兼或...... |
不可兼或.... #
由...可得... >
当且仅当.... =
'''
class FindTruth:def __init__(self):#存储字母及其真值self.Dic = {}self.Lis = []#输入表达式self.__In()#输出真值表self.__Out()#输入def __In(self):#得到表达式Strself.Str = input("input your expression: \n")#筛出字母集合self.Set = set(self.Str).difference(set("()!&|>=#"))#求公式结果def __Sum(self, Str):i = 0 #字符位置s = -1#式子真值while i < len(Str):c = Str[i]#单操作符'!'要做特殊的分类处理if c == "!":#右边是字母if Str[i+1] in self.Set:c = Str[i+1]i = i + 1s0 = self.__Add('!',self.Dic[c]) #右边是左括号else:end = self.__Pei(i+1, Str)s0 = self.__Add('!', self.__Sum(Str[i+1:end+1]))i = end#字母elif c in self.Set:s0 = self.Dic[c]#其它运算符elif c in set("&|>=#"):operat = c#左括号elif c == '(':end = self.__Pei(i, Str)s0 = self.__Sum(Str[i+1:end])i = end#运算结果if s == -1:s = s0s0 = -1elif operat != 0 and s0 != -1:s1 = ss = self.__Add(operat, s, s0)operat = 0s0 = -1i = i + 1return s#配对左右括号def __Pei(self, cur, Str):kflag = 1 # 左括号的数目while not kflag == 0:cur = cur + 1if Str[cur] == '(':kflag = kflag + 1elif Str[cur] == ')':kflag = kflag - 1return cur #运算操作def __Add(self, operator, a, b = -1):#b默认为-1时,表示是单操作符号' ! 'if operator == '!':boo = not aelif operator == '&':boo = a and belif operator == '|':boo = a or belif operator == '#':boo = ((not a) or (not b)) and (a or b)elif operator == '>':boo = (not a) or belif operator == '=':boo = ((not a) and (not b)) or (a and b)else:print("there is no such operator")if boo:return 1else:return 0#输出def __Out(self):#将字母放入dict和ListS = ''for c in self.Set:self.Dic[c] = 0self.Lis.append(c)S = S + c + ' 'print(S, self.Str)self.__Count(0)#构造2^n的序列def __Count(self, i):#是结尾,打印 + 运算if i == len(self.Lis):S = ''for l in self.Lis:S = S + str(self.Dic[l]) + ' 'print(S,self.__Sum(self.Str))return#不是结尾,递归赋值self.Dic[self.Lis[i]] = 0self.__Count(i+1)self.Dic[self.Lis[i]] = 1self.__Count(i+1)if __name__ == '__main__':F = FindTruth()
python - 根据表达式打印真值表相关推荐
- python正则表达
http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html 要匹配一个模式,前后的数字块是相同的,中间是字母,比如111aadf111 这就 ...
- python中的递归思想_使用python语言表达分形与递归
Fibonacci数列 Fibonacci数列是一个很有趣的结构,每后一项都等于前两项之和.它的前几位如下:0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 134.. ...
- python整除表达 mod_[零基础学python]啰嗦的除法
除法啰嗦的,不仅是python. 整数除以整数 看官请在启动idle之后,练习下面的运算: >>> 2/5 0 >>> 2.0/5 0.4 >>> ...
- python正则表达regex_Python 正则表达式(RegEx)
版权所有,未经许可,禁止转载 正则表达式是组成搜索模式的字符序列. 正则表达式用于按指定的搜索模式搜索字符串. 正则表达式(RegEx)模块 Python有一个名为re的内置包,用来处理正则表达式. ...
- python代码表达失恋_Python 经典面试题汇总之网络篇
网络篇 1.简述 OSI 七层协议 物理层:定义物理设备标准,如网线的接口类型.光纤的接口类型.各种传输介质. 数据链路层:定义如何传输格式化数据,以及如何访问物理介质. 网络层:定义逻辑网络地址. ...
- python代码表达元旦节_2020元旦的python学习
效率好低今天(我爱屁股,毕竟今天好歹爬上黄金了hhh) 总结一下今天学的东西吧 + 加 - 减 * 乘 / 除 // 整除(取商) % 取余 ** 指数(x**y=xy ) 1.+可以用来连接多个字符 ...
- python 正则表达函数_python笔记-正则表达式常用函数
1.re.findall()函数 语法:re.findall(pattern,string,flags=0) --> list(列表) 列出字符串中模式的所有匹配项,并作为一个列表返回.如果无匹 ...
- python怎么表达我喜欢你_如何用含蓄的话表达我喜欢你 含蓄表达我喜欢你的句子大全...
有的时候,一句简单的我喜欢你,总是很难讲出来,有时喜欢可以不用直接表达出来,含蓄的表达方法也让人很心动,那么,如何用含蓄的话表达我喜欢你?下面八宝网小编就带来含蓄表达我喜欢你的句子大全. 如何用含蓄的 ...
- TouchDesigner常用python语句表达
Derivative TouchDesigner 是一款基于3D动画和VFX的实时节点的图形生成器.它是一种基于节点的可视化编程语言,它以节点形式构建视觉网络,并集成了许多交互设备组件.TouchDe ...
最新文章
- 基于SSM实现在校学生考试系统
- POJ 1293 - Duty Free Shop 01背包记录所选物品
- linux下watch常见用法,watch命令详解(linux)
- 关于目录操作walk
- PHP配置限制文件大小上传
- 终于解决H3C交换机reset saved-configuration后不能启动的问题
- js中递归调用返回值为undefined问题
- 【分布式定时任务】定时任务实现几种方式
- phpcms 文件:index.html 不可写,phpcms uploadfile不可写怎么办
- 用 Amazon Web Services 进行云计算,第 3 部分:用 EC2 根据需要提供服务器
- 手把手教你刷github提交记录
- “双减”政策下的少儿编程市场:前8月融资12起,资本加持下何时跑出“独角兽”?...
- C语言课设——宿舍管理
- ITU BT 601建议及与ITU BT656 的区别
- 看不懂Offer上的岗位?这一篇统统给你说明白!
- crontab shell 每5秒执行_linux定时任务crontab 实现每秒执行一次的方法
- 计算机毕业设计开题报告(电商网站类)模板
- 关于PPP拨号 和 AT指令实现GPRS模块联网的疑问
- 抓住屌丝心理才是王道
- Lr CC使用几何面板中的直立控件调整图片教程