from abc import abstractmethod

class Tree:

    @abstractmethod
    def tree_map(self, func):
        pass 

    @abstractmethod
    def tree_filter(self, func, filler):
        pass 

    @abstractmethod
    def tree_andmap(self, func):
        pass 

    @abstractmethod
    def tree_ormap(self, func):
        pass 

    @abstractmethod
    def __eq__(self, other):
        pass

class Node(Tree):

    def __init__(self, left, right):
        self.left = left
        self.right = right

    def tree_map(self, func):
        return Node(self.left.tree_map(func), self.right.tree_map(func))

    def tree_filter(self, func, filler):
        return Node(self.left.tree_filter(func, filler), self.right.tree_filter(func, filler))

    def tree_andmap(self, func):
        return self.left.tree_andmap(func) and self.right.tree_andmap(func)

    def tree_ormap(self, func):
        return self.left.tree_ormap(func) or self.right.tree_ormap(func)
    
    def __eq__(self, other):
        if isinstance(other, Node):
            return self.left == other.left and self.right == other.right
        return False

class Leaf(Tree):

    def __init__(self, value):
        self.value = value

    def tree_map(self, func):
        return Leaf(func(self.value))

    def tree_filter(self, func, filler):
        if func(self.value):
            return Leaf(filler)
        else:
            return self

    def tree_andmap(self, func):
        return func(self.value)

    def tree_ormap(self, func):
        return func(self.value)
    
    def __eq__(self, other):
        if isinstance(other, Leaf):
            return self.value == other.value 
        return False