Exemple #1
0
class Calculator:
    def __init__(self):
        self.functions = {
            'EXP': Function(numpy.exp),
            'LOG': Function(numpy.log),
            'SIN': Function(numpy.sin),
            'COS': Function(numpy.cos),
            'SQRT': Function(numpy.sqrt)
        }

        self.operators = {
            'ADD': Operator(numpy.add, 0),
            'PLUS': Operator(numpy.add, 0),
            'MULTIPLY': Operator(numpy.multiply, 1),
            'TIMES': Operator(numpy.multiply, 1),
            'DIVIDE': Operator(numpy.divide, 1),
            'SUBTRACT': Operator(numpy.subtract, 0),
            'MINUS': Operator(numpy.subtract, 0)
        }

        self.output_queue = Queue()
        self.input_queue = Queue()

    def evaluate(self):
        """
        ...
        """
        stack = Stack()
        for i in range(self.output_queue.size()):
            element = self.output_queue.pop()
            if isinstance(element, numbers.Number):
                stack.push(element)
            elif isinstance(element, Function):
                num = stack.pop()
                calculated_value = element.execute(num)
                stack.push(calculated_value)
            elif isinstance(element, Operator):
                num1 = stack.pop()
                num2 = stack.pop()
                calculated_value = element.execute(num2, num1)
                stack.push(calculated_value)
            else:
                raise Exception("Wrong type in the output_queue")

        if stack.size() != 1:
            raise Exception("Stack should be of size 1.")

        return stack.pop()

    def convert_queue_to_rpn(self):
        """
        ...
        """
        operator_stack = Stack()
        for i in range(self.input_queue.size()):
            element = self.input_queue.pop()
            if isinstance(element, numbers.Number):
                self.output_queue.push(element)
            elif isinstance(element, Function):
                operator_stack.push(element)
            elif element == "(":
                operator_stack.push(element)
            elif element == ")":
                while operator_stack.peek() != "(":
                    self.output_queue.push(operator_stack.pop())
                operator_stack.pop()
            elif isinstance(element, Operator):
                while operator_stack.size() != 0:
                    next_element = operator_stack.peek()
                    if isinstance(next_element, Operator):
                        if next_element.strength < element.strength:
                            break
                    elif next_element == "(":
                        break
                    self.output_queue.push(operator_stack.pop())
                operator_stack.push(element)
            else:
                raise Exception("Wrong type in input queue")

        for i in range(operator_stack.size()):
            self.output_queue.push(operator_stack.pop())

    def text_parser(self, text):
        """
        parse text with regex
        """
        text = text.replace(" ", "").upper()

        # Make match strings for regex
        functions = "|".join(["^" + func for func in self.functions.keys()])
        operators = "|".join(["^" + func for func in self.operators.keys()])
        parenthesis = "^[()]"
        nums = "^[-1234567890]+"

        while text != "":
            check_num = re.search(nums, text)  # Check if number
            if check_num is not None:
                matched_num = check_num.__getitem__(0)
                self.input_queue.push(float(matched_num))
                text = text[len(matched_num)::]
                continue

            check_par = re.search(parenthesis, text)  # Check if parenthesis
            if check_par is not None:
                matched_par = check_par.__getitem__(0)
                self.input_queue.push(matched_par)
                text = text[1::]
                continue

            check_op = re.search(operators, text)  # Check if operator
            if check_op is not None:
                matched_op = check_op.__getitem__(0)
                self.input_queue.push(self.operators[matched_op])
                text = text[len(matched_op)::]
                continue

            check_func = re.search(functions, text)  # Check if function
            if check_func is not None:
                matched_func = check_func.__getitem__(0)
                self.input_queue.push(self.functions[matched_func])
                text = text[len(matched_func)::]
                continue

        return self.input_queue

    def calculate(self, input_str):
        """
        Put everything together
        """
        self.text_parser(input_str)
        self.convert_queue_to_rpn()
        return self.evaluate()
class Calculator():
    def __init__(self):
        # Define the functions supported by linking them to Python
        # functions. These can be made elsewhere in the program,
        # or imported (e.g., from numpy)
        self.functions = {
            'EXP': Function(numpy.exp),
            'LOG': Function(numpy.log),
            'SIN': Function(numpy.sin),
            'COS': Function(numpy.cos),
            'SQRT': Function(numpy.sqrt)
        }
        # Define the operators supported
        # Link them to Python functions (here: from numpy)
        self.operators = {
            'PLUSS': Operator(numpy.add, 0),
            'GANGE': Operator(numpy.multiply, 1),
            'DELE': Operator(numpy.divide, 1),
            'MINUS': Operator(numpy.subtract, 0)
        }
        # Define the output−queue . The parse text method fills this with RPN.
        # The evaluate_output_queue method evaluates it
        self.output_queue = Queue()
        self.input_queue = Queue()

    def evaluate_output_queue(self):
        if not isinstance(self.output_queue.peek(),
                          Function) and not isinstance(
                              self.output_queue.peek(), Operator):
            raise TypeError("This is not RPN")

    def RSAcalculation(self):
        sta = Stack()
        size = self.output_queue.size()
        for i in range(0, size):
            element = self.output_queue.pop()
            if isinstance(element, numbers.Number):
                sta.push(element)
            elif isinstance(element, Function):
                number = sta.pop()
                sta.push(element.execute(number))
            else:  #element er operator
                number2 = sta.pop()
                number1 = sta.pop()
                sta.push(element.execute(number1, number2))
        return sta.pop()

    def to_RPN(self):
        op_stack = Stack()
        size_input = self.input_queue.size()
        for i in range(0, size_input):
            element = self.input_queue.peek()
            if isinstance(element, numbers.Number):
                self.output_queue.push(self.input_queue.pop())
            elif isinstance(element, Function):
                op_stack.push(self.input_queue.pop())
            elif element == "(":
                op_stack.push(self.input_queue.pop())
            elif element == ")":
                el = op_stack.peek()
                while el != "(":
                    self.output_queue.push(op_stack.pop())
                    el = op_stack.peek()
                op_stack.pop()
                self.input_queue.pop()
            elif isinstance(element, Operator):
                if not op_stack.is_empty():
                    el = op_stack.peek()
                    while (isinstance(el, Operator)
                           and el.strength >= element.strength) or isinstance(
                               el, Function):
                        self.output_queue.push(op_stack.pop())
                        if op_stack.is_empty():
                            break
                        el = op_stack.peek()
                op_stack.push(self.input_queue.pop())
        size_stack = op_stack.size()
        for i in range(0, size_stack):
            self.output_queue.push(op_stack.pop())

    def textparser(self, input_txt):
        txt = input_txt.replace(" ", "").upper()
        nums = "^[-0123456789.]+"
        funcs = "|".join(["^" + func for func in self.functions])
        ops = "|".join(["^" + op for op in self.operators])
        parenths = r"^[\(\)]"
        while txt != "":
            check = re.search(nums, txt)
            if check is not None:
                txt = self.sub_string(txt, check.end)
                self.input_queue.push(float(check.group(0)))
            check = re.search(funcs, txt)
            if check is not None:
                txt = self.sub_string(txt, check.end)
                self.input_queue.push(self.functions[check.group(0)])
            check = re.search(ops, txt)
            if check is not None:
                txt = self.sub_string(txt, check.end)
                self.input_queue.push(self.operators[check.group(0)])
            check = re.search(parenths, txt)
            if check is not None:
                txt = self.sub_string(txt, check.end)
                self.input_queue.push(check.group(0))

    def sub_string(self, string, end):
        if len(string) - 1 < end(0):
            return ""
        return string[end(0):]

    def calculate_expression(self, txt):
        self.textparser(txt)
        self.to_RPN()
        return self.RSAcalculation()