Ejemplo n.º 1
0
    def test_iterator(self):
        stack = Stack(int)

        for i in range(20, 42, 2):
            stack.push(i)

        integers = list(range(20, 42, 2))
        self.assertEqual(len(stack), len(integers), "Size method doesn't work")

        index = len(integers) - 1
        for num in stack:
            self.assertEqual(num, integers[index], "Iterator doesn't work")
            index -= 1

        self.assertEqual(len(stack), 0, "iterator doesn't adjust stack size")
Ejemplo n.º 2
0
def check_parenthesis(expression):
    # the stack for the parenthesis
    parenthesis = Stack()

    # pushing all the left parenthesis in a stack
    for token in tokenize(expression):
        if token == "(":
            parenthesis.push(token)

        # if there's a right parenthesis, check if the stack is empty, that is there is no left parenthesis left
        elif token == ")":
            if parenthesis.is_empty():
                return False
            else:
                parenthesis.pop()

    # at the end, if the stack is empty, return true, all the parenthesis are valid; otherwise, return false
    return parenthesis.is_empty()
Ejemplo n.º 3
0
    def test_push(self):
        stack = Stack()
        stack.push(23)
        stack.push(20)
        self.assertEqual(stack.peek(), 20, "Wrong stack push implementation")
        self.assertEqual(len(stack), 2, "Wrong stack push implementation")

        stack = Stack(bool)
        with self.assertRaises(TypeError):
            stack.push("word")

        for i in range(10):
            if i % 2 == 0:
                stack.push(True)
            else:
                stack.push(False)
        self.assertEqual(stack.size(), 10, "Wrong stack push implementation")
Ejemplo n.º 4
0
    def test_pop(self):
        stack = Stack()
        with self.assertRaises(ValueError):
            stack.pop()
        stack.push([1, 2, 3])
        self.assertEqual(stack.pop()[1], 2, "Stack pops wrong element")
        stack.push("pushed string")
        self.assertEqual(stack.pop(), "pushed string",
                         "Stack pops wrong element")

        stack = Stack(bool)
        with self.assertRaises(ValueError):
            stack.pop()
        stack.push(True)
        stack.push(False)
        stack.pop()
        self.assertTrue(stack.pop(), "Stack pops wrong element")
Ejemplo n.º 5
0
    def test_peek(self):
        stack = Stack()
        self.assertEqual(
            stack.peek(), None,
            "Top element of stack should be None at initialization")
        stack.push(2)
        stack.push("Tests")
        self.assertEqual(stack.peek(), "Tests", "Stack gives wrong peek")

        stack = Stack(float)
        self.assertEqual(
            stack.peek(), None,
            "Top element of stack should be None at initialization")
        stack.push(3.5)
        stack.push(1.27)
        stack.push(2.0)
        self.assertEqual(stack.peek(), 2.0, "Stack gives wrong peek")
Ejemplo n.º 6
0
    def test_empty(self):
        stack = Stack()
        self.assertTrue(stack.is_empty(), "Stack should be empty")
        stack.push("word")
        stack.push("sentence")
        stack.pop()
        self.assertFalse(stack.is_empty(), "Stack should not be empty")

        stack = Stack(int)
        self.assertTrue(stack.is_empty(), "Stack should be empty")

        stack.push(0)
        self.assertFalse(stack.is_empty(), "Stack should not be empty")
Ejemplo n.º 7
0
    def test_size(self):
        stack = Stack()
        self.assertEqual(stack.size(), 0,
                         "Stack size should be 0 at initialization")
        for i in range(1, 41):
            stack.push(i)
            stack.push(i + 1)
            stack.pop()
        self.assertEqual(stack.size(), 40, "Incorrect stack size")

        stack = Stack(str)
        self.assertEqual(stack.size(), 0,
                         "Stack size should be 0 at initialization")
        for l in ["a", "d", "b", "m"]:
            stack.push(l)

        stack.pop()
        self.assertEqual(stack.size(), 3, "Incorrect stack size")
Ejemplo n.º 8
0
    def test_contains(self):
        stack = Stack()
        self.assertFalse(1 in stack, "Stack contains method doesn't work")

        stack.push("word")
        self.assertEqual("word" in stack, stack.contains("word"),
                         "Stack contains method doesn't work")
        self.assertTrue(stack.contains("word"),
                        "Stack contains method doesn't work")

        stack = Stack(elements_type=float)
        stack.push(1.55)
        stack.push(2.3)
        self.assertTrue(2.3 in stack, "Stack contains method doesn't work")
        self.assertTrue(stack.contains(1.55),
                        "Stack contains method doesn't work")

        with self.assertRaises(TypeError):
            boolean = 4 in stack

        with self.assertRaises(TypeError):
            boolean = stack.contains("word")
Ejemplo n.º 9
0
    def test_str(self):
        stack = Stack(int)
        self.assertEqual(
            str(stack), "[]",
            "String representation of stack doesn't work with empty stacks")

        stack.push(0)
        self.assertEqual(
            str(stack), "[0]",
            "String representation of stack doesn't work with singleton stacks"
        )

        for i in [5, 20, 11, 34, 2]:
            stack.push(i)

        self.assertEqual(
            str(stack), "[0, 5, 20, 11, 34, 2]",
            "String representation of stack doesn't work with many elements")

        stack.peek()
        stack.pop()
        stack.pop()
        self.assertEqual(
            str(stack), "[0, 5, 20, 11]",
            "String representation of stack doesn't work after pop and peek operations"
        )

        stack = Stack()
        stack.push(2.5)
        stack.push(0)
        self.assertEqual(str(stack), "[2.5, 0]")
Ejemplo n.º 10
0
    def test_type(self):
        stack = Stack()
        self.assertEqual(stack.type(), None)

        with self.assertRaises(TypeError):
            stack = Stack(elements_type=3)

        stack = Stack(elements_type=list)
        self.assertEqual(stack.type(), list)

        with self.assertRaises(TypeError):
            stack.push("hey")

        stack = Stack(elements_type=str)
        stack.push("world")
        stack.push("hello")
        test_string = stack.pop() + " " + stack.pop()
        self.assertEqual(test_string, "hello world",
                         "Stack with strings doesn't pop correctly")

        with self.assertRaises(TypeError):
            stack.push(123)
Ejemplo n.º 11
0
def evaluate_expression(expression):

    assert type(expression) is str, "Expression must be a string object"

    # check for errors in parenthesis
    if not check_parenthesis(expression):
        raise ArithmeticError("Invalid parenthesis")

    # using the global variable operators_priorities
    global operators_priorities

    # tokenizing the expression and initializing the two stack for the operands and the operators
    tokens = tokenize(expression)
    operands = Stack(elements_type=float)
    operators = Stack(elements_type=str)

    # iterating through the the tokens of the expression
    for token in tokens:
        # pushing the token into the right stack
        try:
            # if the token is a number push into operands stack
            operands.push(float(token))
        # if the token is one of these '(', ')', '*', '/', '+' or '-'
        except ValueError:
            try:
                # if the operators' stack is empty, add the token there
                if operators.is_empty():
                    operators.push(token)

                # if the operator is a '(', add the token to the stack
                elif token == "(":
                    operators.push(token)

                # if the operator is a ')', call the adjust_parenthesis method
                elif token == ")":
                    adjust_parenthesis(operands, operators)

                # if the last operator's priority is less than or equal to the priority of the current operator,
                # add the current operator to the stack again
                elif operators_priorities[operators.peek()] <= operators_priorities[token]:
                    operators.push(token)

                # if the last operator's priority is greater than the priority of the current operator,
                # call the method adjust_stacks and push the operator into the operators' stack
                elif operators_priorities[operators.peek()] > operators_priorities[token]:
                    adjust_stacks(operands, operators, token)
                    operators.push(token)
            # if the token is not supported, raise a Value error
            except KeyError:
                raise ValueError("Non supported attribute in the expression")

    # when we went through all the tokens, check if there's only one value left in the operands' stack and 0 operators
    # in the operators' stack, only then we know we are finished
    if operands.size() != 1 and operators.size() != 0:
        # if the finishing property is not true, then we repeat the operation from the adjust_stacks method,
        # while we know that we are finished
        while operands.size() != 1 and operators.size() != 0:
            # popping the last operator with the last two operands
            operator = operators.pop()
            b = operands.pop()
            a = operands.pop()

            # evaluating the value of the simple expression and pushing it back in the stack
            if operator == "*":
                operands.push(a * b)
            elif operator == "/":
                operands.push(a / b)
            elif operator == "+":
                operands.push(a + b)
            elif operator == "-":
                operands.push(a - b)
            # if the operator is not from the supported ones, raise an exception
            else:
                raise ValueError("The attribute you are specifying is not supported")

        # when we are finished, the operands' stack contains only the result from the expression, so we pop it
        return operands.pop()

    # if we know we are finished, we directly pop the result, since the operands' stack contains only the
    # result from the expression
    else:
        return operands.pop()