Beispiel #1
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")
Beispiel #2
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")
Beispiel #3
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()