from enum import Enum


class Operation(Enum):
    AND = 0
    OR = 1
    XOR = 2
    VALUE = 3


class Node:
    def __init__(
        self,
        operation,
        value,
        left = None,
        right = None,
    ):
        self.operation = operation
        self.value = value
        self.left = left
        self.right = right

def eval_tree(node):
    if node is None:
        raise Exception("root is None")
    if node.operation == Operation.VALUE:
        return

    eval_tree(node.left)
    eval_tree(node.right)

    if node.operation == Operation.AND:
        node.value = node.left.value and node.right.value
    elif node.operation == Operation.OR:
        node.value = node.left.value or node.right.value
    elif node.operation == Operation.XOR:
        node.value = node.left.value ^ node.right.value

def eval_flips(node, root_if_true, root_if_false):
    if node is None:
        raise Exception("node is None")
    if node.operation == Operation.VALUE:
        print(root_if_false if node.value else root_if_true)
        return

    if node.operation == Operation.AND:
        # If rhs is false, lhs doesn't affect the result.
        eval_flips(node.left, root_if_true if node.right.value else root_if_false, root_if_false)
        # If lhs is false, rhs doesn't affect the result.
        eval_flips(node.right, root_if_true if node.left.value else root_if_false, root_if_false)
    elif node.operation == Operation.OR:
        eval_flips(node.left, root_if_true, root_if_true if node.right.value else root_if_false)
        eval_flips(node.right, root_if_true, root_if_true if node.left.value else root_if_false)
    elif node.operation == Operation.XOR:
        # متروك للطالب
        pass

def example1() -> Node:
    return Node(
        operation=Operation.AND,
        value=None,
        left=Node(
            operation=Operation.OR,
            value=None,
            left=Node(operation=Operation.VALUE, value=True),
            right=Node(
                operation=Operation.AND,
                value=None,
                left=Node(operation=Operation.VALUE, value=True),
                right=Node(operation=Operation.VALUE, value=False),
            ),
        ),
        right=Node(
            operation=Operation.OR,
            value=None,
            left=Node(operation=Operation.VALUE, value=True),
            right=Node(operation=Operation.VALUE, value=False),
        ),
    )


def main():
    root = example1()
    eval_tree(root)
    eval_flips(root, True, False)


if __name__ == "__main__":
    main()