Source code for kyu_2.evaluate_mathematical_expression.evaluate

"""
Evaluate mathematical expression.

Given a mathematical expression as a
string you must return the result as a number.

Created by Egor Kostan.
GitHub: https://github.com/ikostan
"""

OPERATORS = ['*', '/', '+', '-']


[docs] def calculate(i: int, char: str, strings: list) -> None: """ Calculate math expression. :param i: int :param char: str :param strings: list :return: None """ # pylint: disable=R0801 a: float = float(strings[i - 1]) b: float = float(strings[i + 1]) if char == '*': strings[i] = str(a * b) if char == '/': strings[i] = str(a / b) # pylint: enable=R0801 del strings[i + 1] del strings[i - 1]
[docs] def process_math_expression(string: str, operators: list) -> str: """ Process math expression. :param string: str :param operators: list :return: str """ strings: list = [s for s in string.split(' ') if bool(s != '+')] while any(s in operators for s in strings): for i, char in enumerate(strings): if char in operators: calculate(i, char, strings) break return ' '.join(strings)
[docs] def bracket_start(strings: list) -> int: """ Return index of first (open) bracket. :param strings: list :return: int """ a: int = ([i for i, strg in enumerate(strings) if strg == '('])[-1] return a
[docs] def bracket_end(strings: list, start: int) -> int: """ Return index of last (close) bracket. :param strings: :param start: :return: """ return strings[start:].index(')') + start
[docs] def process_brackets(strings: list) -> str: """ Test bracket processing. Process brackets in order to convert input string into math expression. :param strings: list :return: str """ while '(' in strings: start = bracket_start(strings=strings) end = bracket_end(strings=strings, start=start) if len(strings[start + 1: end]) < 3: del strings[end] del strings[start] if len(strings[start + 1: end]) > 2: temp: str = ' '.join(strings[start + 1: end]) temp = process_duplicate_minus(temp) temp = process_math_expression(temp, ['*', '/']) temp_lst: list = [float(t) for t in temp.split() if t != '+'] temp = str(sum(temp_lst)) tmp_strings: list = strings[:start] tmp_strings.append(temp) if end < len(strings) - 1: tmp_strings += strings[end + 1:] strings = tmp_strings return ' '.join(strings)
[docs] def process_duplicate_minus(string: str) -> str: """ Eliminate duplicate minus. :param string: str :return: str """ done: bool = False strings: list = string.split(' ') while not done: done = True for i, s in enumerate(strings): if s == '-': if strings[i + 1] == '-': done = False strings[i] = '+' del strings[i + 1] break str_temp = [t.isdigit() for t in strings[i + 1]] if any(str_temp): done = False strings[i] = str(float(strings[i + 1]) * (-1)) del strings[i + 1] break if s == '+': if strings[i + 1] == '-': done = False del strings[i] break return ' '.join(strings)
[docs] def calc(string: str) -> float: """ Calculate math expression from input string. :param string: str :return: float """ string = ''.join([s for s in string if s != ' ']) strings: list = [] while string: temp: str = '' temp, string = check_conditions(strings, string, temp) string = ' '.join(strings) string = ''.join(string.split('+')) strings = string.split() string = process_brackets(strings) string = process_duplicate_minus(string) string = process_math_expression(string, ['*', '/']) string_lst: list = string.split(' ') string_lst = [float(s) for s in string_lst] string = str(sum(string_lst)) return float(string)
[docs] def check_conditions(strings: list, string: str, temp: str) -> tuple[str, str]: """ Test string normalization. Normalize string input by checking conditions. :param strings: list :param string: str :param temp: str :return: tuple(str, str) """ for i, s in enumerate(string): if s.isdigit(): temp += s if (s in ''.join(OPERATORS) + '()' or i == len(string) - 1) and temp: strings.append(temp) if s in '()': strings.append(s) if i + 1 < len(string): string = string[i + 1:] else: string = '' break if s in OPERATORS: strings.append(s) if i + 1 < len(string): string = string[i + 1:] break if i == len(string) - 1: string = '' return temp, string