-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathpuzzler.py
More file actions
80 lines (69 loc) · 1.95 KB
/
puzzler.py
File metadata and controls
80 lines (69 loc) · 1.95 KB
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
"""
Solve logic puzzles.
TODO: compare to http://www.eecs.berkeley.edu/~bh/v3ch2/math.html
"""
import operator
from peglet import Parser # Prerequisite: pip install peglet
import dd
def mk_var(name):
return dd.Variable(enter(name))
var_names = []
def enter(name):
for v, vname in enumerate(var_names):
if vname == name:
return v
v = len(var_names)
var_names.append(name)
return v
# XXX whitespace *with* a newline shouldn't be an AND -- too error-prone.
# Only with lhs and rhs on the same line should whitespace be AND.
#
# XXX what's a good precedence/associativity for impl?
grammar = r"""
formula = _ expr !.
expr = sentence , _ expr mk_and
| sentence
sentence = sum /=/ _ sum mk_eqv
| sum
sum = term \| _ sum mk_or
| term => _ term mk_impl
| term
term = factor term mk_and
| factor
factor = ~ _ primary mk_not
| primary
primary = \( _ expr \) _
| id _ mk_var
id = ([A-Za-z_]\w*) _
_ = (?:\s|#[^\n]*)*
"""
parse = Parser(grammar,
mk_eqv = dd.Equiv,
mk_impl = dd.Implies,
mk_and = operator.and_,
mk_or = operator.or_,
mk_not = operator.inv,
mk_var = mk_var)
def solve(puzzle_text):
condition, = parse(puzzle_text)
if dd.is_valid(condition):
print("Valid.")
else:
show(dd.satisfy(condition, 1))
def show(opt_env):
if opt_env is None:
print("Unsatisfiable.")
else:
for k, v in sorted(opt_env.items()):
if k is not None:
print("%s%s" % ("" if v else "~", var_names[k]))
## solve(' hey (there | ~there), ~hey | ~there')
#. hey
#. ~there
## solve(' hey (there, ~there)')
#. Unsatisfiable.
## solve('a=>b = ~b=>~a')
#. Valid.
if __name__ == '__main__':
import sys
solve(sys.stdin.read()) # (try it on carroll or wise-pigs)