Ejemplo n.º 1
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.º 2
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.º 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 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()