Skip to content

Instantly share code, notes, and snippets.

@1buran
Created December 12, 2019 04:55
Show Gist options
  • Save 1buran/82aa26c69b448992ce901d0a985ad248 to your computer and use it in GitHub Desktop.
Save 1buran/82aa26c69b448992ce901d0a985ad248 to your computer and use it in GitHub Desktop.
Traversing of logical expressions
"""
Example of implementation of logical expression traversing.
The typical logical expressions look like: "n1 AND n2" or "n1 OR n2" or more
complex(nested): ((n1 AND n2) OR (n3 AND n4)). The last example can be
represent as tree:
OR
/ \
AND AND
/ \ / \
n1 n2 n3 n4
"""
class Node:
"""
>>> n1 = Node("sdsd")
>>> n1.value == "sdsd" and n1.left is None and n1.right is None
True
>>> n2 = Node(2)
>>> n3 = Node(3, n1, n2)
>>> n3.left == n1 and n3.right == n2 and n3.value == 3
True
>>> n1, n2 = Node(1), Node(2)
>>> n12 = n1 & n2
>>> n12.value == "AND"
True
>>> n12.left is n1 and n12.right is n2
True
>>> isinstance(n12, LogicalAndNode)
True
>>> n3, n4 = Node(3), Node(4)
>>> n34 = n3 | n4
>>> n34.value == "OR"
True
>>> n34.left is n3 and n34.right is n4
True
>>> isinstance(n34, LogicalOrNode)
True
>>> str(n34)
'(3 OR 4)'
>>> str(n12)
'(1 AND 2)'
>>> str(n12 & n34)
'((1 AND 2) AND (3 OR 4))'
"""
def __init__(self, value, left=None, right=None):
self.value = value
self.left = left
self.right = right
def __str__(self):
return str(self.value)
def __and__(self, other):
return LogicalAndNode(self, other)
def __or__(self, other):
return LogicalOrNode(self, other)
class RootNode(Node):
"""Dummy class for easy detect root nodes."""
def __str__(self):
stack = []
def traverse(root):
if isinstance(root, RootNode):
stack.append(")")
stack.append(root.right)
stack.append(f' {root.value} ')
stack.append(root.left)
stack.append("(")
try:
node = stack.pop()
if isinstance(node, RootNode):
traverse(node)
elif isinstance(node, Node):
stack.append(node.value)
else:
stack.append(node)
except IndexError:
return
traverse(self)
return f"{''.join(str(stack.pop()) for x in range(len(stack)))}"
class LogicalOrNode(RootNode):
"""
>>> n1 = LogicalOrNode()
>>> n1.value == "OR" and n1.left is None and n1.right is None
True
>>> n2, n3 = Node(2), Node(3)
>>> n23 = LogicalOrNode(n2, n3)
>>> n23.value == "OR" and n23.left is n2 and n23.right is n3
True
>>> str(n23)
'(2 OR 3)'
"""
def __init__(self, left=None, right=None):
super().__init__('OR', left, right)
class LogicalAndNode(RootNode):
"""
>>> n1 = LogicalAndNode()
>>> n1.value == "AND" and n1.left is None and n1.right is None
True
>>> n2, n3 = Node(2), Node(3)
>>> n23 = LogicalAndNode(n2, n3)
>>> n23.value == "AND" and n23.left is n2 and n23.right is n3
True
>>> str(n23)
'(2 AND 3)'
"""
def __init__(self, left=None, right=None):
super().__init__('AND', left, right)
import doctest
doctest.testmod(verbose=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment