Exemplo n.º 1
0
def balanced_parentheses(paren_str):
    """problem involving applications of stack"""

    # filter out all values besides brackets
    matches = re.finditer(r'[(){}[\]]+', paren_str)
    parsed_iter = itertools.chain.from_iterable(
                            result.group() 
                            for result in matches)
    
    opening = Stack()
    
    for i in parsed_iter:
        if i in ("(", "{", "["):
            opening.add(i)
        
        else:
            if not opening.isEmpty():
                if   i == ")" and opening.peek() == "(":
                    opening.get()
                elif i == "}" and opening.peek() == "{":
                    opening.get()
                elif i == "]" and opening.peek() == "[":
                    opening.get()
                else:
                    return False
                
            else:
                return False

    return True  
Exemplo n.º 2
0
def infixtopostfix(string):

    comp = string.split(' ')
    output = []
    operator_precedence = {"+": 1, "-": 1, "/": 2, "*": 2, "(": 3, ")": 3}
    operator_stack = Stack()

    for value in comp:
        if value in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' or value in '0123456789':
            output.append(value)
        elif value == '(':
            operator_stack.push(value)
        elif value == ')':
            operator = operator_stack.pop()
            while operator != '(':
                output.append(operator)
                operator = operator_stack.pop()
        else:
            while not operator_stack.isEmpty() and \
                    operator_precedence[operator_stack.peek()] <= operator_precedence[value]:
                output.append(operator_stack.pop())
            operator_stack.push(value)

    while not operator_stack.isEmpty():
        token = operator_stack.pop()
        output.append(token)

    return ' '.join(output)
def infixToPostfix(infixexpr):
    precedence = {}
    precedence["*"] = 3
    precedence["/"] = 3
    precedence["+"] = 2
    precedence["-"] = 2
    precedence["("] = 1
    opStack = Stack()
    postfixList = []
    tokenList = infixexpr.split()

    for token in tokenList:
        if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789":
            postfixList.append(token)
        elif token == '(':
            opStack.push(token)
        elif token == ')':
            topToken = opStack.pop()
            while topToken != '(':
                postfixList.append(topToken)
                topToken = opStack.pop()
        else:
            while (not opStack.isEmpty()) and \
               (precedence[opStack.peek()] >= precedence[token]):
                postfixList.append(opStack.pop())
            opStack.push(token)

    while not opStack.isEmpty():
        postfixList.append(opStack.pop())
    return " ".join(postfixList)
Exemplo n.º 4
0
def test_stack():
	stack = Stack()
	stack.push(3)
	stack.push(2)
	assert stack.peek() == 2
	assert stack.pop() == 2
	assert stack.pop() == 3
	assert stack.is_empty()
Exemplo n.º 5
0
def test_push():
    stack, arr = Stack(), []
    assert(stack.is_empty())
    for expected in range(ITERS):
        stack.push(expected)
        arr = [expected] + arr
        actual = stack.peek()
        assert(len(stack) == len(arr))
        assert(expected == actual)
        assert(not stack.is_empty())
Exemplo n.º 6
0
class TestStack(unittest.TestCase):
    @staticmethod
    def add_to_structure(self, items):
        for i in items:
            self.structure.add(i)

    def setUp(self):
        self.structure = Stack()

    def test_structure_isEmpty(self):
        self.assertEqual(self.structure.isEmpty(), True)

        self.add_to_structure(self, range(3))
        self.assertEqual(self.structure.isEmpty(), False)

    def test_structure_peek(self):

        structure = self.add_to_structure(
            self, iter(['people', 'potatoes', 'pansies']))
        self.assertEqual(self.structure.peek(), 'pansies')

    def test_structure_get_length(self):
        structure = self.add_to_structure(self, range(5))
        self.assertEqual(self.structure.get_length(), 5)

    def test_structure_get(self):
        structure = self.add_to_structure(self, range(3))

        # test that first in are first out
        for i in reversed(range(3)):
            self.assertEqual(self.structure.get(), i)

    def test_empty_items(self):
        # for when get, or peek is called on empty structure
        self.assertRaises(EmptyItemsError, lambda: self.structure.get())
        self.assertRaises(EmptyItemsError, lambda: self.structure.peek())
    def calculations(self):
        """
        This is where the calculator does its magic.

        To see how this function works, please reference the textbook material on Chapter 3 Stacks. This algorithm was
        built by making an algorithm that takes an infix expression and transforms it into a postfix expression
        (2+2 --> 22+). Then, by taking that postfix expression and processing the operators and operands it until there
        is only 1 element in the stack, we get the postfix answer, which is the same answer for the infix expression.
        (22+ --> 4)

        It is possible to build a calculator with simply those 2 algorithms linked up to each other. However, this
        function is a hybrid of the two where it is able to simultaneously work with operators and operands, such that
        when an infix expression is determined to be in postfix expression, we immediately calculate the answer.
        """
        precedent = {'*': 3, '/': 3, '+': 2, '-': 2, '(': 1}
        operator_stack = Stack()
        operand_stack = Stack()

        for item in self.final_infix:
            if item in string.ascii_letters:
                operand_stack.push(self.numbers.get(item))
            elif item == '(':
                operator_stack.push(item)
            elif item == ')':
                # Here be dragons.
                top_of_stack = operator_stack.pop()
                while top_of_stack != '(':
                    operand2 = float(operand_stack.pop())
                    operand1 = float(operand_stack.pop())
                    operand_stack.push(self.do_math(top_of_stack, operand1, operand2))
                    top_of_stack = operator_stack.pop()
            elif item in precedent:
                while (not operator_stack.isempty()) and precedent[operator_stack.peek()] >= precedent[item]:
                    operand2 = float(operand_stack.pop())
                    operand1 = float(operand_stack.pop())
                    operand_stack.push(self.do_math(operator_stack.pop(), operand1, operand2))
                operator_stack.push(item)
            elif item == '~':
                # This is a helper variable to signal the end of infix expression and empty all stacks.
                while not operator_stack.isempty():
                    operand2 = float(operand_stack.pop())
                    operand1 = float(operand_stack.pop())
                    operand_stack.push(self.do_math(operator_stack.pop(), operand1, operand2))
            else:
                raise TypeError('Error: Calculations blew up.')

        self.answer = operand_stack.pop()
Exemplo n.º 8
0
def test_pop():
    stack, arr = Stack(), []
    assert(stack.is_empty())
    with pytest.raises(AssertionError):
        stack.pop()
    for _ in range(ITERS):
        expected = random.randrange(MAX_VAL)
        stack.push(expected)
        actual = stack.peek()
        arr = [expected] + arr
        assert(len(stack) == len(arr))
        assert(actual == expected)
    for _ in range(ITERS):
        expected, actual = arr[0], stack.pop()
        arr = arr[1:]
        assert(len(stack) == len(arr))
        assert(actual == expected)
    assert(stack.is_empty())
    with pytest.raises(AssertionError):
        stack.pop()
Exemplo n.º 9
0
class TestStack(unittest.TestCase):  # LIFO

    def setUp(self):
        self.emptyStack = Stack()
        self.Stack = Stack()

        for i in range(5):
            self.Stack.push(i)

    def test_repr(self):
        '''Test returning the stack as a string literal.'''
        self.assertEqual(repr(self.emptyStack), str(()))
        tup = (1, 3.14, 'foo', True)

        for i in tup:
            self.emptyStack.push(i)

        self.assertEqual(repr(self.emptyStack), str((True, 'foo', 3.14, 1)))

    def test_len_size(self):
        '''Test returning the size of the stack.'''
        for i in range(100):
            self.emptyStack.push(i)

        self.assertEqual(len(self.emptyStack), 100)
        self.assertEqual(self.emptyStack.size(), 100)

        self.emptyStack.pop()
        self.assertEqual(len(self.emptyStack), 99)
        self.assertEqual(self.emptyStack.size(), 99)

    def test_tuple(self):
        '''Test returning the stack as a tuple literal.'''
        self.assertEqual(tuple(self.emptyStack), ())
        tup = (1, 3.14, 'foo', True)

        for i in tup:
            self.emptyStack.push(i)

        self.assertEqual(tuple(self.emptyStack), (True, 'foo', 3.14, 1))

    def test_list(self):
        '''Test returning the stack as a list literal.'''
        self.assertEqual(list(self.emptyStack), [])
        li = [1, 3.14, 'foo', True]

        for i in li:
            self.emptyStack.push(i)

        self.assertEqual(list(self.emptyStack), [True, 'foo', 3.14, 1])

    def test_push(self):
        '''Test pushing items on top of the stack.'''
        self.Stack.push(True)
        self.assertEqual(tuple(self.Stack), (True, 4, 3, 2, 1, 0))

    def test_pop(self):
        '''Test popping off and returning the top of the stack.'''
        self.assertEqual(self.Stack.pop(), 4)
        self.assertEqual(tuple(self.Stack), (3, 2, 1, 0))
        self.assertEqual(self.Stack.pop(), 3)
        self.assertEqual(self.Stack.pop(), 2)
        self.assertEqual(self.Stack.pop(), 1)
        self.assertEqual(self.Stack.pop(), 0)
        self.assertEqual(tuple(self.Stack), ())

        with self.assertRaises(ValueError):
            self.Stack.pop()

    def test_peek(self):
        '''Test peeking at the top of the stack w/o modifying the stack.'''
        self.assertEqual(self.Stack.peek(), 4)

        with self.assertRaises(ValueError):
            self.emptyStack.peek()
Exemplo n.º 10
0
def single_dfs(big_list, current):
    stack = Stack()
    explored = Queue()
    pointer = current

    stack.push(pointer)
    explored.enqueue(pointer)
    tra_model = Tra_model()

    while True:

        if stack.isEmpty():
            break
        else:
            pointer = stack.peek()

        x = pointer[0]
        y = pointer[1]
        if big_list[x][y + 1] == " ":  #if right is empty
            pointer = tra_model.move_right(pointer)
            stack.push(pointer)
            explored.enqueue(pointer)
            x = pointer[0]
            y = pointer[1]
            big_list[x][y] = "#"
            continue  #return to the top of the loop

        if big_list[x][y + 1] == ".":
            pointer = tra_model.move_right(pointer)
            stack.push(pointer)
            explored.enqueue(pointer)
            break

        if big_list[x][y + 1] == "%" or "#":  #if right is wall
            if big_list[x + 1][y] == " ":  #if down is empty
                pointer = tra_model.move_down(pointer)
                stack.push(pointer)
                explored.enqueue(pointer)
                x = pointer[0]
                y = pointer[1]
                big_list[x][y] = "#"
                continue

            if big_list[x + 1][y] == ".":
                pointer = tra_model.move_down(pointer)
                stack.push(pointer)
                explored.enqueue(pointer)
                break

            if big_list[x + 1][y] == "%" or "#":  # if down is wall
                if big_list[x - 1][y] == " ":  # if up is empty

                    pointer = tra_model.move_up(pointer)
                    stack.push(pointer)
                    explored.enqueue(pointer)
                    x = pointer[0]
                    y = pointer[1]
                    big_list[x][y] = "#"
                    continue  # return to the top of the loop

                if big_list[x - 1][y] == ".":
                    pointer = tra_model.move_up(pointer)
                    stack.push(pointer)
                    explored.enqueue(pointer)
                    break

                if big_list[x - 1][y] == "%" or "#":  #if up is wall
                    if big_list[x][y - 1] == " ":  #if left is empty
                        pointer = tra_model.move_left(pointer)
                        stack.push(pointer)
                        explored.enqueue(pointer)
                        x = pointer[0]
                        y = pointer[1]
                        big_list[x][y] = "#"
                        continue  #return to the top

                    if big_list[x - 1][y] == ".":
                        pointer = tra_model.move_left(pointer)
                        stack.push(pointer)
                        explored.enqueue(pointer)
                        break
                    if big_list[x][y - 1] == "%" or "#":
                        big_list[x][y] = "*"
                        stack.pop()

    expanded = 0
    for i in explored.items:
        expanded += 1
        x = i[0]
        y = i[1]

        if big_list[x][y] == "*":
            big_list[x][y] = " "

    steps = 0
    for i in explored.items:
        x = i[0]
        y = i[1]

        if big_list[x][y] == "#":
            steps += 1

    return explored, big_list, steps, expanded
def test_peak_at_stack():
    stack = Stack()
    stack.push('a')

    assert stack.peek() == 'a'
Exemplo n.º 12
0
class TestDataStructures(unittest.TestCase):

    def setUp(self):
        self.stack = Stack(range(1, 6))
        self.queue = Queue(range(1, 6))
        self.single = SinglyLinkedList()
        self.double = DoublyLinkedList()
        self.btree = BinaryTree()

    # STACK
    def test_stack_push(self):
        self.stack.push(6)
        self.assertEqual(self.stack.stack, range(1, 7)) 

    def test_stack_pop(self):
        self.assertEqual(self.stack.pop(), 5)
        self.assertEqual(self.stack.pop(), 4)

    def test_stack_peek(self):
        self.assertEqual(self.stack.peek(), 5)

    # QUEUE
    def test_queue_push(self):
        self.queue.push(6)
        self.assertEqual(self.queue.queue, range(1, 7))

    def test_queue_pop(self):
        self.assertEqual(self.queue.pop(), 1)
        self.assertEqual(self.queue.pop(), 2)

    def test_queue_peek(self):
        self.assertEqual(self.queue.peek(), 1)
        self.queue.pop()
        self.assertEqual(self.queue.peek(), 2)

    # SINGLY-LINKED LIST
    def test_add_nodes_to_single(self):
        node1, node2, node3 = Node(1), Node(2), Node(3)
        self.single._insert(node1)
        self.single._insert(node2, node1)
        self.assertEqual(self.single.head.value, 1)
        next = self.single.head.next
        self.assertEqual(next, node2)
        self.assertEqual(next.value, 2)
        self.single._insert(node3, node2)
        nextnext = self.single.head.next.next
        self.assertEqual(nextnext, node3)

    def test_add_node_to_beginning_of_single(self):
        node0, node1 = Node(0), Node(1)
        self.single._insert(node1)
        self.single._insert(node0)
        self.assertEqual(self.single.head.value, 0)
        self.assertEqual(self.single.head.next.value, 1)

    def test_remove_nodes_single(self):
        node1, node2, node3, node4 = Node(1), Node(2), Node(3), Node(4)
        self.single._insert(node1)
        self.single._insert(node2, node1)
        self.single._insert(node3, node2)
        self.single._insert(node4, node3)
        self.single._remove(node2)
        self.assertEqual(node2.next, node4)

    def test_remove_node_from_beginning_single(self):
        node1, node2, node3 = Node(1), Node(2), Node(3)
        self.single._insert(node1)
        self.single._insert(node2, node1)
        self.single._insert(node3, node2)
        self.single._remove()
        self.assertEqual(self.single.head, node2)

    def test_single_iteration(self):
        node1, node2, node3, node4 = Node(1), Node(2), Node(3), Node(4)
        self.single._insert(node1)
        self.single._insert(node2, node1)
        self.single._insert(node3, node2)
        self.single._insert(node4, node3)
        self.assertEqual([node for node in self.single], [node1, node2, node3, node4])

    def test_add_node_to_single_for_real(self):
        self.single.insert(2, 0)
        self.assertEqual(self.single[0].value, 2)
        self.single.insert(1, 0)
        self.assertEqual(self.single[0].value, 1)
        self.single.insert(3, 2)
        self.assertEqual(self.single[2].value, 3)
        self.single.insert(4, 100)
        self.assertEqual(self.single[3].value, 4)

    def test_remove_node_from_single_for_real(self):
        for i in range(4, 0, -1):
            self.single.insert(i, 0)
        # [1, 2, 3, 4]
        self.single.remove(1)
        # [1, 3, 4]
        self.assertEqual(self.single[1].value, 3)
        self.single.remove(2)
        # [1, 3]
        self.assertEqual(self.single[0].value, 1)
        self.assertEqual(self.single[1].value, 3)

   # DOUBLE-LINKED LIST
    def test_iteration_double(self):
        node1, node2, node3 = Node(1), Node(2), Node(3)
        node1.next, node2.next, node3.next = node2, node3, None
        node1.prev, node2.prev, node3.prev = None, node1, node2
        self.double.head = node1
        self.double.tail = node3
        # test __iter__
        self.assertEqual([str(i) for i in self.double], [str(i) for i in range(1, 4)])
        # test iterating over reversed
        self.assertEqual([str(i) for i in reversed(self.double)], [str(i) for i in range(3, 0, -1)])

    def test_double_slicing(self):
        node1, node2, node3 = Node(1), Node(2), Node(3)
        node1.next, node2.next, node3.next = node2, node3, None
        node1.prev, node2.prev, node3.prev = None, node1, node2
        self.double.head = node1
        self.double.tail = node3
        self.assertEqual(self.double[0].value, 1)
        self.assertEqual(self.double[1].value, 2)
        self.assertEqual(self.double[2].value, 3)
        self.assertRaises(IndexError, lambda val: self.double[val], 3)

    def test_base_insert_moving_forwards_with_double(self):
        node1, node2, node3 = Node(1), Node(2), Node(3)
        self.double._insert(node1)
        self.assertTrue(test_node(self.double[0], 1, None, None))
        self.assertTrue(test_linked_list(self.double, self.double[0], self.double[0]))

        self.double._insert(node3, node1)
        self.assertTrue(test_node(self.double[0], 1, 3, None))
        self.assertTrue(test_node(self.double[1], 3, None, 1))
        self.assertTrue(test_linked_list(self.double, self.double[0], self.double[1]))

        self.double._insert(node2, node1)
        self.assertTrue(test_node(self.double[0], 1, 2, None))
        self.assertTrue(test_node(self.double[1], 2, 3, 1))
        self.assertTrue(test_node(self.double[2], 3, None, 2))
        self.assertTrue(test_linked_list(self.double, self.double[0], self.double[2]))

        self.assertEqual(str(self.double), str([str(i) for i in range(1, 4)]))

    def test_base_insert_moving_backwards_with_double(self):
        node1, node2, node3 = Node(1), Node(2), Node(3)
        # insert node3 at the beginning/end of the list
        self.double._rev_insert(node3)
        self.assertTrue(test_node(self.double[0], 3, None, None))
        self.assertTrue(test_linked_list(self.double, self.double[0], self.double[0]))
        # insert node one before node 3 ([node1, node3])
        self.double._rev_insert(node1, node3)
        self.assertTrue(test_node(self.double[0], 1, 3, None))
        self.assertTrue(test_node(self.double[1], 3, None, 1))
        self.assertTrue(test_linked_list(self.double, self.double[0], self.double[1]))
        # insert node2 before node3 ([node1, node2, node3])
        self.double._rev_insert(node2, node3)
        self.assertTrue(test_node(self.double[0], 1, 2, None))
        self.assertTrue(test_node(self.double[1], 2, 3, 1))
        self.assertTrue(test_node(self.double[2], 3, None, 2))
        self.assertTrue(test_linked_list(self.double, self.double[0], self.double[2]))
        # check that the array is [node1, node2, node3]
        self.assertEqual(str(self.double), str([str(i) for i in range(1, 4)]))

    def test_insert_at_beginning_of_double(self):
        self.double.insert(2, 0)
        self.assertTrue(test_node(self.double[0], 2, None, None))
        self.assertTrue(test_linked_list(self.double, self.double[0], self.double[0]))
        self.double.insert(1, 0)
        self.assertTrue(test_node(self.double[0], 1, 2, None))
        self.assertTrue(test_node(self.double[1], 2, None, 1))
        self.assertTrue(test_linked_list(self.double, self.double[0], self.double[1]))

    def test_insert_in_middle_and_end_of_double(self):
        self.double.insert(1, 0)
        self.double.insert(3, 1)
        self.assertTrue(test_node(self.double[0], 1, 3, None))
        self.assertTrue(test_node(self.double[1], 3, None, 1))
        self.assertTrue(test_linked_list(self.double, self.double[0], self.double[1]))
        self.double.insert(2, 1) 
        self.assertTrue(test_node(self.double[0], 1, 2, None))
        self.assertTrue(test_node(self.double[1], 2, 3, 1))
        self.assertTrue(test_node(self.double[2], 3, None, 2))
        self.assertTrue(test_linked_list(self.double, self.double[0], self.double[2]))
        self.double.insert(5, 3) 
        self.assertTrue(test_node(self.double[0], 1, 2, None))
        self.assertTrue(test_node(self.double[1], 2, 3, 1))
        self.assertTrue(test_node(self.double[2], 3, 5, 2))
        self.assertTrue(test_node(self.double[3], 5, None, 3))
        self.assertTrue(test_linked_list(self.double, self.double[0], self.double[3]))
        self.double.insert(4, 3) 
        self.assertTrue(test_node(self.double[0], 1, 2, None))
        self.assertTrue(test_node(self.double[1], 2, 3, 1))
        self.assertTrue(test_node(self.double[2], 3, 4, 2))
        self.assertTrue(test_node(self.double[3], 4, 5, 3))
        self.assertTrue(test_node(self.double[4], 5, None, 4))
        self.assertTrue(test_linked_list(self.double, self.double[0], self.double[4]))

    # Binary Tree
    def test_binary_node_equality(self):
        one = BinaryNode(1)
        one2 = BinaryNode(1)
        self.assertTrue(one == one2)
        two = BinaryNode(2)
        self.assertFalse(one == two)

    def test_add_internal_child_to_binary_node(self):
        one = BinaryNode(1)
        two = BinaryNode(2)
        three = BinaryNode(3)
        one.left = three
        # one = {left: 3, right: None}
        one.insert(two, three)
        self.assertTrue(test_binary_node(one, 1, 2, None, None))
        self.assertTrue(test_binary_node(two, 2, 3, None, 1))
        self.assertTrue(test_binary_node(three, 3, None, None, 2))

    def test_add_external_child_to_binary_node(self):
        one = BinaryNode(1)
        two = BinaryNode(2)
        one.insert(two)
        self.assertTrue(test_binary_node(one, 1, 2, None, None))
        self.assertTrue(test_binary_node(two, 2, None, None, 1))
        three = BinaryNode(3)
        one.insert(three)
        self.assertTrue(test_binary_node(one, 1, 2, 3, None))
        self.assertTrue(test_binary_node(two, 2, None, None, 1))
        self.assertTrue(test_binary_node(three, 3, None, None, 1))
        four = BinaryNode(4)
        two.insert(four)
        self.assertTrue(test_binary_node(two, 2, 4, None, 1))
        self.assertTrue(test_binary_node(four, 4, None, None, 2))

    def test_depth_first_generation(self):
        self.btree.root = deep_btree()
        self.assertEquals([int(str(n)) for n in self.btree.depth_gen(self.btree.root)], range(1, 9))

    def test_breadth_first_generation(self):
        self.btree.root = wide_btree()
        self.assertEqual([int(str(n)) for n in self.btree.breadth_gen([self.btree.root])], range(1, 9))

    def test_binary_tree_iteration(self):
        self.btree.root = deep_btree()
        self.assertEquals([int(str(n)) for n in self.btree], range(1, 9))

    def test_contains(self):
        self.btree.root = deep_btree()
        for i in range(1, 9):
            self.assertTrue(i in self.btree)
        self.assertFalse(0 in self.btree)
        self.assertFalse(9 in self.btree)

    def test_insert_into_binary_tree(self):
        ## note - indexing grabs the node with that VALUE, not the node that exists at that index
        #       1
        self.btree.insert(1)
        self.assertTrue(test_binary_node(self.btree[1], 1, None, None, None))
        self.btree.insert(4, 1)
        #       1
        #      /
        #     4
        self.assertTrue(test_binary_node(self.btree[1], 1, 4, None, None))
        self.assertTrue(test_binary_node(self.btree[4], 4, None, None, 1))
        self.btree.insert(3, 1)
        #       1
        #      / \
        #     4   3
        self.assertTrue(test_binary_node(self.btree[1], 1, 4, 3, None))
        self.assertTrue(test_binary_node(self.btree[4], 4, None, None, 1))
        self.assertTrue(test_binary_node(self.btree[3], 3, None, None, 1))
        self.btree.insert(2, 1, 4)
        #       1
        #      / \
        #     2   3
        #    /
        #   4
        self.assertTrue(test_binary_node(self.btree[1], 1, 2, 3, None))
        self.assertTrue(test_binary_node(self.btree[2], 2, 4, None, 1))
        self.assertTrue(test_binary_node(self.btree[3], 3, None, None, 1))
        self.assertTrue(test_binary_node(self.btree[4], 4, None, None, 2))


    # Binary Search Tree
    def test_binary_search_node(self):
        root = binary_search_tree()
        for i in range(1, 9):
            self.assertTrue(root.search(i))
        self.assertFalse(root.search(0))
        self.assertFalse(root.search(9))

    def test_binary_search_insert(self):
    #               5
    #             /    \
    #           3        8
    #         /  \     /
    #       2     4   6

        root = BinarySearchNode(5)
        self.assertTrue(test_binary_node(root, 5, None, None, None))
        root.insert(3)
        self.assertTrue(test_binary_node(root, 5, 3, None, None))
        self.assertTrue(test_binary_node(root[3], 3, None, None, 5))
        root.insert(8)
        self.assertTrue(test_binary_node(root, 5, 3, 8, None))
        self.assertTrue(test_binary_node(root[3], 3, None, None, 5))
        self.assertTrue(test_binary_node(root[8], 8, None, None, 5))
        root.insert(4)
        self.assertTrue(test_binary_node(root, 5, 3, 8, None))
        self.assertTrue(test_binary_node(root[3], 3, None, 4, 5))
        self.assertTrue(test_binary_node(root[8], 8, None, None, 5))
        self.assertTrue(test_binary_node(root[4], 4, None, None, 3))
        root.insert(2)
        self.assertTrue(test_binary_node(root, 5, 3, 8, None))
        self.assertTrue(test_binary_node(root[3], 3, 2, 4, 5))
        self.assertTrue(test_binary_node(root[8], 8, None, None, 5))
        self.assertTrue(test_binary_node(root[2], 2, None, None, 3))
        self.assertTrue(test_binary_node(root[4], 4, None, None, 3))
        root.insert(6)
        self.assertTrue(test_binary_node(root, 5, 3, 8, None))
        self.assertTrue(test_binary_node(root[3], 3, 2, 4, 5))
        self.assertTrue(test_binary_node(root[8], 8, 6, None, 5))
        self.assertTrue(test_binary_node(root[2], 2, None, None, 3))
        self.assertTrue(test_binary_node(root[4], 4, None, None, 3))
        self.assertTrue(test_binary_node(root[6], 6, None, None, 8))

    # def test_binary_search_remove_external_node(self):
    #     root = binary_search_tree()
    #     root.remove(1)
    #     self.assertTrue(test_binary_node(root, 5, 3, 8, None))
    #     self.assertTrue(test_binary_node(root[3], 3, 2, 4, 5))
    #     self.assertTrue(test_binary_node(root[8], 8, 6, None, 5))
    #     self.assertTrue(test_binary_node(root[2], 2, None, None, 3))
    #     self.assertTrue(test_binary_node(root[4], 4, None, None, 3))
    #     self.assertTrue(test_binary_node(root[6], 6, None, 7, 8))
    #     self.assertTrue(test_binary_node(root[7], 7, None, None, 6))
    #     self.assertFalse(1 in root)
    #     self.assertFalse(root.search(1))

    def test_binary_search_remove_internal_node_without_children(self):
        root = binary_search_tree()
        root.remove(3, root[4])
        self.assertTrue(test_binary_node(root, 5, 4, 8, None))
        self.assertTrue(test_binary_node(root[4], 4, 2, None, 5))
        self.assertTrue(test_binary_node(root[8], 8, 6, None, 5))
        self.assertTrue(test_binary_node(root[2], 2, 1, None, 4))
        self.assertTrue(test_binary_node(root[6], 6, None, 7, 8))
        self.assertTrue(test_binary_node(root[7], 7, None, None, 6))
        self.assertFalse(3 in root)

    def test_binary_search_remove_internal_node_with_children1(self):
        root = binary_search_tree()
        root.insert(3.5)
        root.insert(4.5)
        root.remove(3, root[4])

        self.assertTrue(test_binary_node(root, 5, 4, 8, None))
        self.assertTrue(test_binary_node(root[4], 4, 3.5, 4.5, 5))
        self.assertTrue(test_binary_node(root[8], 8, 6, None, 5))
        self.assertTrue(test_binary_node(root[2], 2, 1, None, 3.5))
        self.assertTrue(test_binary_node(root[6], 6, None, 7, 8))
        self.assertTrue(test_binary_node(root[1], 1, None, None, 2))
        self.assertTrue(test_binary_node(root[3.5], 3.5, 2, None, 4))
        self.assertTrue(test_binary_node(root[4.5], 4.5, None, None, 4))
        self.assertTrue(test_binary_node(root[7], 7, None, None, 6))
        self.assertFalse(3 in root)

    def test_binary_search_remove_internal_node_with_children2(self):
        root = binary_search_tree()
        root.insert(3.5)
        root.insert(4.5)
        root.remove(3, root[2])

        self.assertTrue(test_binary_node(root, 5, 2, 8, None))
        self.assertTrue(test_binary_node(root[2], 2, 1, 4, 5))
        self.assertTrue(test_binary_node(root[8], 8, 6, None, 5))
        self.assertTrue(test_binary_node(root[6], 6, None, 7, 8))
        self.assertTrue(test_binary_node(root[1], 1, None, None, 2))
        self.assertTrue(test_binary_node(root[4], 4, 3.5, 4.5, 2))
        self.assertTrue(test_binary_node(root[3.5], 3.5, None, None, 4))
        self.assertTrue(test_binary_node(root[4.5], 4.5, None, None, 4))
        self.assertTrue(test_binary_node(root[7], 7, None, None, 6))
        self.assertFalse(3 in root)

    # HEAP
    def test_heap_iteration(self):
        heap = Heap(max_heap())
        self.assertEqual([int(str(n)) for n in heap.breadth()], [17, 15, 10, 6, 10, 7])
        self.assertEqual([int(str(n)) for n in heap], [17, 15, 10, 6, 10, 7])
        self.assertEqual(heap.flatten(), [17, 15, 10, 6, 10, 7])

    def test_find_open_with_empty_aunt(self):
        node17 = HeapNode(17)
        node15 = HeapNode(15)
        node11 = HeapNode(11)
        node6 = HeapNode(6)
        node10 = HeapNode(10)
        node17.left = node15
        node17.right = node11
        node15.left = node6
        node15.right = HeapNode(10)

        heap = Heap(node17)
        self.assertEqual(heap[-1].value, 10)
        self.assertEqual(heap.find_open(), (node11, 'left'))

    def test_find_open_with_single_child_aunt(self):
        node17 = HeapNode(17)
        node15 = HeapNode(15)
        node11 = HeapNode(11)
        node6 = HeapNode(6)
        node10 = HeapNode(10)
        node7 = HeapNode(7)
        node17.left = node15
        node17.right = node11
        node15.left = node6
        node15.right = HeapNode(10)
        node11.left = node7

        heap = Heap(node17)
        self.assertEqual(heap[-1].value, 7)
        self.assertEqual(heap.find_open(), (node11, 'right'))

    def test_find_open_with_non_empty_aunt(self):
        node17 = HeapNode(17)
        node15 = HeapNode(15)
        node11 = HeapNode(11)
        node6 = HeapNode(6)
        node10 = HeapNode(10)
        node7 = HeapNode(7)
        node5 = HeapNode(5)
        node17.left = node15
        node17.right = node11
        node15.left = node6
        node15.right = HeapNode(10)
        node11.left = node7
        node11.right = node5
        
        heap = Heap(node17)
        self.assertEqual(heap[-1].value, 5)
        self.assertEqual(heap.find_open(), (node6, 'left'))

    def test_insert(self):
        node17 = HeapNode(17)
        heap = Heap(node17)
        heap.insert(15)
        self.assertTrue(test_binary_node(heap.root, 17, 15, None, None))
        self.assertTrue(test_binary_node(heap.root.left, 15, None, None, 17))
        heap.insert(10)
        self.assertTrue(test_binary_node(heap.root, 17, 15, 10, None))
        self.assertTrue(test_binary_node(heap.root.left, 15, None, None, 17))        
        self.assertTrue(test_binary_node(heap.root.right, 10, None, None, 17))
        heap.insert(6)
        self.assertTrue(test_binary_node(heap.root, 17, 15, 10, None))
        self.assertTrue(test_binary_node(heap.root.left, 15, 6, None, 17))        
        self.assertTrue(test_binary_node(heap.root.right, 10, None, None, 17))
        self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 15))
        heap.insert(10)
        self.assertTrue(test_binary_node(heap.root, 17, 15, 10, None))
        self.assertTrue(test_binary_node(heap.root.left, 15, 6, 10, 17))        
        self.assertTrue(test_binary_node(heap.root.right, 10, None, None, 17))
        self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 15))
        self.assertTrue(test_binary_node(heap.root.left.right, 10, None, None, 15))
        heap.insert(7)
        self.assertTrue(test_binary_node(heap.root, 17, 15, 10, None))
        self.assertTrue(test_binary_node(heap.root.left, 15, 6, 10, 17))        
        self.assertTrue(test_binary_node(heap.root.right, 10, 7, None, 17))
        self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 15))
        self.assertTrue(test_binary_node(heap.root.left.right, 10, None, None, 15))
        self.assertTrue(test_binary_node(heap.root.right.left, 7, None, None, 10))

    def test_bubble(self):

        #               17                      17                  100
        #             /    \                  /    \               /    \
        #          15        10    -->     15       100    -->   15       17
        #         /  \      /  \          /  \      /  \        /  \     /  \
        #       6     10   7   100      6     10   7   10     6     10  7   10

        heap = Heap(max_heap())
        parent = heap.root.right
        last = HeapNode(100)
        parent.right = last
        last.parent = parent
        heap.bubble(last)

        self.assertTrue(test_binary_node(heap.root, 100, 15, 17, None))
        self.assertTrue(test_binary_node(heap.root.right, 17, 7, 10, 100))
        self.assertTrue(test_binary_node(heap.root.right.left, 7, None, None, 17))
        self.assertTrue(test_binary_node(heap.root.right.right, 10, None, None, 17))

        #             100                  100                  100
        #            /    \               /    \               /    \
        #          15       17   -->    15       17    -->  99       17
        #         /  \     /  \        /  \     /  \        /  \     /  \
        #       6     10  7   10     99   10  7   10     15     10  7   10
        #      /                     /                   /
        #     99                   6                   6

        parent = heap.root.left.left
        last = HeapNode(99)
        last.parent = parent
        parent.left = last
        heap.bubble(last)
        self.assertTrue(test_binary_node(heap.root, 100, 99, 17, None))
        self.assertTrue(test_binary_node(heap.root.left, 99, 15, 10, 100))
        self.assertTrue(test_binary_node(heap.root.left.left, 15, 6, None, 99))
        self.assertTrue(test_binary_node(heap.root.left.right, 10, None, None, 99))
        self.assertTrue(test_binary_node(heap.root.left.left.left, 6, None, None, 15))

        #             100                  100                  100
        #            /    \               /    \               /    \
        #          99       17   -->    99       17    -->  100       17
        #         /  \     /  \        /  \     /  \        /  \      /  \
        #       15    10  7   10     15  100  7   10     15    99   7   10
        #      /  \   /             / \   /              /  \   /
        #     6   12 100          6  12 10             6   12 10

        fifteen = heap.root.left.left
        twelve = HeapNode(12)
        twelve.parent = fifteen
        fifteen.right = twelve

        ten = heap.root.left.right
        last = HeapNode(100)
        ten.left = last
        last.parent = ten
        heap.bubble(last)
        self.assertTrue(test_binary_node(heap.root, 100, 100, 17, None))
        self.assertTrue(test_binary_node(heap.root.left, 100, 15, 99, 100))
        self.assertTrue(test_binary_node(heap.root.left.left, 15, 6, 12, 100))
        self.assertTrue(test_binary_node(heap.root.left.right, 99, 10, None, 100))


    def test_insertion_with_percolation(self):
        #               17
        #             /    \
        #          15        10
        #         /  \      /
        #       6     10   7

        #     6
        six = HeapNode(6)
        heap = Heap(six)
        self.assertTrue(test_binary_node(heap.root, 6, None, None, None))

        #     6             10
        #    /    -->     /
        #  10           6
        heap.insert(10)
        self.assertTrue(test_binary_node(heap.root, 10, 6, None, None))
        self.assertTrue(test_binary_node(heap.root.left, 6, None, None, 10))          
        #     10             10
        #    /  \  -->     /   \
        #  6     7       6      7
        heap.insert(7)
        self.assertTrue(test_binary_node(heap.root, 10, 6, 7, None))
        self.assertTrue(test_binary_node(heap.root.left, 6, None, None, 10)) 
        self.assertTrue(test_binary_node(heap.root.right, 7, None, None, 10))
        #      10            15
        #     /  \  -->     /   \
        #   6     7       10      7
        #  /              / 
        # 15             6
        heap.insert(15)
        self.assertTrue(test_binary_node(heap.root, 15, 10, 7, None))
        self.assertTrue(test_binary_node(heap.root.left, 10, 6, None, 15)) 
        self.assertTrue(test_binary_node(heap.root.right, 7, None, None, 15))
        self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 10))
        #      15            17
        #     /  \  -->     /   \
        #   10    7       15      7
        #  /  \          /  \
        # 6    17       6    10
        heap.insert(17)
        self.assertTrue(test_binary_node(heap.root, 17, 15, 7, None))
        self.assertTrue(test_binary_node(heap.root.left, 15, 6, 10, 17)) 
        self.assertTrue(test_binary_node(heap.root.right, 7, None, None, 17))
        self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 15))
        self.assertTrue(test_binary_node(heap.root.left.right, 10, None, None, 15))
        #       17             17    
        #      /   \  -->     /   \   
        #    15     7       15     11
        #   /  \   /       /  \   /  
        #  6   10 11      6   10 7  
        heap.insert(11)
        self.assertTrue(test_binary_node(heap.root, 17, 15, 11, None))
        self.assertTrue(test_binary_node(heap.root.left, 15, 6, 10, 17)) 
        self.assertTrue(test_binary_node(heap.root.right, 11, 7, None, 17))
        self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 15))
        self.assertTrue(test_binary_node(heap.root.left.right, 10, None, None, 15))
        self.assertTrue(test_binary_node(heap.root.right.left, 7, None, None, 11))

    def test_build_from_array(self):
        heap1 = [17, 15, 11, 6, 10, 7]
        heap2 = [6, 10, 7, 15, 17, 11]
        heap = Heap(array=heap1)
        self.assertTrue(test_binary_node(heap.root, 17, 15, 11, None))
        self.assertTrue(test_binary_node(heap.root.left, 15, 6, 10, 17)) 
        self.assertTrue(test_binary_node(heap.root.right, 11, 7, None, 17))
        self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 15))
        self.assertTrue(test_binary_node(heap.root.left.right, 10, None, None, 15))
        self.assertTrue(test_binary_node(heap.root.right.left, 7, None, None, 11)) 
        heap = Heap(array=heap2)
        self.assertTrue(test_binary_node(heap.root, 17, 15, 11, None))
        self.assertTrue(test_binary_node(heap.root.left, 15, 6, 10, 17)) 
        self.assertTrue(test_binary_node(heap.root.right, 11, 7, None, 17))
        self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 15))
        self.assertTrue(test_binary_node(heap.root.left.right, 10, None, None, 15))
        self.assertTrue(test_binary_node(heap.root.right.left, 7, None, None, 11)) 

    def test_delete(self):

        #          17                  7                  15                  15          
        #        /    \              /    \              /    \              /    \    
        #     15        11  -->   15        11  -->   7        11   -->   10        11
        #    /  \      /         /  \                /  \                /  \        
        #  6     10   7        6     10            6     10            6     7       
        heap = Heap(max_heap())
        heap[2].value = 11
        heap.delete_root()
        self.assertTrue(test_binary_node(heap.root, 15, 10, 11, None))
        self.assertTrue(test_binary_node(heap.root.left, 10, 6, 7, 15)) 
        self.assertTrue(test_binary_node(heap.root.right, 11, None, None, 15))
        self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 10))
        self.assertTrue(test_binary_node(heap.root.left.right, 7, None, None, 10))
        #         15                  7                  11    
        #       /    \              /    \             /    \  
        #     10      11  -->    10       11  -->   10       7
        #    /  \               /                  /           
        #  6     7            6                  6             
        heap.delete_root()
        self.assertTrue(test_binary_node(heap.root, 11, 10, 7, None))
        self.assertTrue(test_binary_node(heap.root.left, 10, 6, None, 11)) 
        self.assertTrue(test_binary_node(heap.root.right, 7, None, None, 11))
        self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 10))
        #          11               6                 10           
        #        /    \           /    \            /    \        
        #     10       7  -->   10      7   -->   6       7
        #    /                                                      
        #  6                                                       
        heap.delete_root()
        self.assertTrue(test_binary_node(heap.root, 10, 6, 7, None))
        self.assertTrue(test_binary_node(heap.root.left, 6, None, None, 10)) 
        self.assertTrue(test_binary_node(heap.root.right, 7, None, None, 10))
        #      10             7        
        #    /    \  -->    /       
        #  6       7      6     
        heap.delete_root()
        self.assertTrue(test_binary_node(heap.root, 7, 6, None, None))
        self.assertTrue(test_binary_node(heap.root.left, 6, None, None, 7)) 
        #      7                
        #    /   -->   6
        #  6             
        heap.delete_root()
        self.assertTrue(test_binary_node(heap.root, 6, None, None, None))
        #   6   -->  None
        heap.delete_root()
        self.assertFalse(heap.root)