ssd
和cbd
助教一起上了一门课,课内常有逻辑表达式证明的作业,ssd
学长实在是太菜了,没办法看清楚这些表达式的值,想请你写个程序画出这些表达式对应的真值表,求求你帮帮他。
对于只能取真
和假
的简单命题变元,通过逻辑连接词
(例如与
、或
、非
)等连接起来的表达式称为命题
表征命题在所有输入可能取值状态下对应的值的表格即为真值表。
例如现在有两个简单命题变元p
和q
,通过逻辑连接词$\wedge$连接为命题$p \wedge q$,则该命题的真值表即为
$p$ | $q$ | $p\wedge q$ |
---|---|---|
F | F | F |
F | T | F |
T | F | F |
T | T | T |
对于逻辑连接词而言,满足一元逻辑连接词优先于二元运算连接词,二元运算连接词之间优先级相同,但如果存在括号,则括号内的优先级最高
命题的同优先级的演算遵循从左到右的规则
两行输入
第一行为多个字母,由空格隔开,表示这一组数据中的出现的简单变元的字符 (简单变元字符仅可能为小写字母,保证不会重复)
第二行为一行逻辑表达式,由第一行中出现过的字符和逻辑连接词组成,为方便大家表示,本题规定逻辑连接词包括&
,|
,~
,(
,)
其意义如下
&
:与运算|
:或运算~
:非运算(
:左括号)
:右括号令输入的简单变元个数为$n$(这个$n$需要大家自己计数)
则总输出为$2^n+1$行,每行$n+1$列,列于列之间以|
隔开,列内容与|
符号之间留出一个空格
第一行为表头,前$n$列为输入的简单命题变元字符,第$n+1$列为$R$,代表Result
接下来$n$行,每行代表每种取值可能对应的命题结果,真以T表示,假以F表示
输入顺序满足命题变元代表的二进制数的升序,以包括四个简单命题变元的命题为例
FFFF
即0000
代表0
,则首先输出,FFFT
即0001
代表1
,第二个输出,依次类推,直到所有情况输出完成
p q
p&q
| p | q | R |
| F | F | F |
| F | T | F |
| T | F | F |
| T | T | T |
p q r
(((p&~q)|(~p&q))&~r)|(~((p&~q)|(~p&q))&r)
| p | q | r | R |
| F | F | F | F |
| F | F | T | T |
| F | T | F | T |
| F | T | T | F |
| T | F | F | T |
| T | F | T | F |
| T | T | F | F |
| T | T | T | T |
给出的简单命题变元不会超过$10$个
命题中逻辑连接词+命题变元长度不超过300个
本题输入末尾存在'\r'字符,请想办法消除它的干扰
用栈可以解决表达式计算的问题
样例2是全加器的本位数真值哦嘻嘻
如果你不知道怎么遍历命题变元的各种取值可能的话,去E2请教一下木木枭学长吧!
Author:ssd
下面给出用栈计算包含(+
,-
,*
,/
)算数表达式的思路
(考虑括号的话要怎么样做呢?)
以表达式1+2*3-4/5为例
首先,我们建立两个栈分别为数字栈与符号栈
向数字栈中压入第一个数字1
判断符号栈为空,直接压入一个运算符+
再向数字栈中压入一个数字,为2
判断符号栈非空,判断待压字符与栈顶字符的优先级,*优先于+,将*压入字符栈
向数字栈中压入下一个数字3
判断符号栈非空,判断待压字符与栈顶字符优先级,-号的优先级低于*,暂缓压栈
弹出数字栈中顶部两个数字,弹出符号栈中的*号,计算2*3=6,将结果6压入数字栈
重复判断符号栈非空,判断顶部符号于-的优先级和+号相同,继续暂缓压栈
弹出数字栈中顶部两个数字1和6,弹出符号栈的+,计算1+6=7,将7压入数字栈
判断符号栈为空,压入-号
压入数字4
判断符号栈非空,判断待压运算符 / 与 - 的优先级, / 的优先级高于 - ,压入 / 号
向数字栈压入数字5
此时以及没有待读取的字符了,开始回溯栈中的信息
判断字符栈非空,弹出两个数字5和4,弹出符号 / 计算4/5=0.8,将0.8压入数字栈.
判断字符栈非空,弹出数字0.8和7,弹出 - 号,计算 7-0.8-6.2,将6.2压入数字栈
此时字符堆栈已空,弹出数字栈顶的数字,此时数字栈中唯一的数字即为结果6.2