-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathTruthTableGenerator.py
187 lines (156 loc) · 5.86 KB
/
TruthTableGenerator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# -*- coding: utf-8 -*-
# Copyright (c) 2020, xehoth
# All rights reserved.
#
# @file TruthTableGenerator.py
# @author: xehoth
from typing import List
import re
import sys
class Proposition:
def __init__(self, value=False):
self.value = value
# ->
def __rshift__(self, rhs):
return Proposition(not (self.value and not rhs.value))
# or
def __add__(self, rhs):
return Proposition(self.value or rhs.value)
# and
def __mul__(self, rhs):
return Proposition(self.value and rhs.value)
# not
def __invert__(self):
return Proposition(not self.value)
# <->
def __eq__(self, rhs):
return Proposition((self.value and rhs.value) or (not self.value and not rhs.value))
# ^
def __ne__(self, rhs):
return Proposition(self.value != rhs.value)
def getTableElement(s: str, markdown=False, l = -1) -> str:
l = (len(s) if (l == -1 or markdown == True) else l)
if markdown:
s = "$" + s + "$"
s = s.center(l + 2)
return s + "|" if markdown else s
def getPropositions(s: str) -> List[str]:
return list(sorted(set(re.findall(r'\w+', s.replace("T", "").replace("F", "")))))
def getEvalExpression(s: str):
# not
s = s.replace("!", "~").replace("not", "~").replace(
"¬", "~").replace(r"\neg", "~")
# and
s = s.replace("&", "*").replace(r"\wedge", "*").replace("and",
"*").replace("∧", "*")
# or
s = s.replace("|", "+").replace(r"\vee", "+").replace("or",
"+").replace("∨", "+").replace("v", "+")
# <->
s = s.replace("<->", "==").replace("↔",
"==").replace(r"\leftrightarrow", "==")
# ->
s = s.replace("->", ">>").replace("→", ">>").replace(r"\rightarrow", ">>")
# ^
s = s.replace("^", "!=").replace("⊕", "!=")
return s
def getLatexExpression(s: str) -> str:
return s.replace("~", r" \neg ").replace("*", r" \wedge ").replace(
"+", r" \vee ").replace("==", r" \leftrightarrow ").replace(">>", r" \rightarrow ").replace("!=", r" \oplus ")
def generateTruthTable(expression: str, reverse=False, markdown=False, file=sys.stdout) -> None:
# True
T = Proposition(True)
# False
F = Proposition(False)
# strip
expression = expression.strip()
# eval string
s = getEvalExpression(expression)
# tautology & conflict
tautology = True
conflict = False
if markdown:
expression = getLatexExpression(s)
props = getPropositions(s)
n = len(props)
# prop eval buffer
buf = [Proposition() for i in range(n)] + [T, F]
if markdown:
print("|", end='', file=file)
for i in props + [expression]:
print(getTableElement(i, markdown=markdown), sep='', end='', file=file)
print(file=file)
if markdown:
print("|", end='', file=file)
for i in range(n + 1):
print(" :--: |", end='', file=file)
print()
states = range(0, 1 << n)
for state in reversed(states) if reverse else states:
if markdown:
print("|", end='', file=file)
for i in range(n):
buf[i].value = (state >> (n - i - 1)) & 1 == 1
print(getTableElement(
"FT"[buf[i].value], markdown=markdown, l = len(props[i])), end='', file=file)
res = eval("(" + s + ").value",{v: buf[i] for i, v in enumerate(props + ['T', 'F'])})
print(getTableElement("FT"[res], markdown=markdown, l = len(expression)), file=file)
tautology = tautology and res
conflict = conflict or res
if tautology:
print("\nIt's tautological.\n", file=file)
if not conflict:
print("\nIt's conflict.\n", file=file)
def main(inputFile=sys.stdin, outputFile=sys.stdout, reverse=False, markdown=False) -> None:
for s in inputFile:
generateTruthTable(s, reverse=reverse,
markdown=markdown, file=outputFile)
def printHelp() -> None:
print("""Truth Table Generator
usage: [-h | --help] [-i | --input <file path>]
[-o | --output <file path>] [-c | --console]
[-m | --markdown] [-r | --reverse ]
[-i | --input <file path>]
input from <file path>
[-o | --output <file path>]
output the result to <file path>
[-c | --console]
console mode (default)
[-m | --markdown]
generate markdown table
[-r | --reverse]
reverse the enumerate order (default F -> T)
""")
if __name__ == "__main__":
args = sys.argv
if len(args) == 1:
main()
elif "-h" in args or "--help" in args:
printHelp()
elif "-c" in args or "--console" in args:
main()
else:
markdown = "-m" in args or "--markdown" in args
reverse = "-r" in args or "--reverse" in args
inputFile = ''
outputFile = ''
if "-i" in args:
inputFile = args[args.index("-i") + 1]
if "--input" in args:
inputFile = args[args.index("--input") + 1]
if "-o" in args:
outputFile = args[args.index("-o") + 1]
if "--output" in args:
outputFile = args[args.index("--output") + 1]
if not inputFile and not outputFile:
main(reverse=reverse, markdown=markdown)
elif not inputFile and outputFile:
with open(outputFile, "w", encoding='utf-8') as o:
main(outputFile=o, reverse=reverse, markdown=markdown)
elif inputFile and not outputFile:
with open(inputFile, "r", encoding='utf-8') as i:
main(inputFile=i, reverse=reverse, markdown=markdown)
else:
with open(inputFile, "r", encoding='utf-8') as i, open(outputFile, "w", encoding='utf-8') as o:
main(inputFile=i, outputFile=o,
reverse=reverse, markdown=markdown)