diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 00000000..c825f3de --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..94a25f7f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/final_task/pycalc/__init__.py b/final_task/pycalc/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/final_task/pycalc/arithmetic.py b/final_task/pycalc/arithmetic.py new file mode 100644 index 00000000..894f8ac6 --- /dev/null +++ b/final_task/pycalc/arithmetic.py @@ -0,0 +1,28 @@ +def subtraction(first_parameter, second_parameter): + return float(first_parameter) - float(second_parameter) + + +def add(first_parameter, second_parameter): + return float(first_parameter) + float(second_parameter) + + +def multiply(first_parameter, second_parameter): + return float(first_parameter) * float(second_parameter) + + +def division(first_parameter, second_parameter): + if float(second_parameter) == 0: + return "Error: division by zero" + return float(first_parameter) / float(second_parameter) + + +def power(first_parameter, second_parameter): + return float(first_parameter) ** float(second_parameter) + + +def integer_division(first_parameter, second_parameter): + return float(first_parameter) // float(second_parameter) + + +def modulo_division(first_parameter, second_parameter): + return float(first_parameter) % float(second_parameter) diff --git a/final_task/pycalc/calculate_expression.py b/final_task/pycalc/calculate_expression.py new file mode 100644 index 00000000..51b10bab --- /dev/null +++ b/final_task/pycalc/calculate_expression.py @@ -0,0 +1,76 @@ +from pycalc import arithmetic +import re + + +def calculate(value): + """ It is a calculator. It can be use Math operation""" + + if type(value) is not str: + print('It expected str got ' + type(value).__name__) + + access_operators = ['+', '-', '*', '/', '//', '%', '**'] + operators = re.findall(r'(\D*[^-.?\d?])', value) + digits = re.findall(r'(-*\.*\d+\.*\d*)', value) + if len(operators) == len(digits): + return "Error: you miss digits" + # check accessible operators + for operator in operators: + format_operator = operator.replace(' ', '') + if format_operator not in access_operators: + return "Error: not accessible operator '" + operator + "'" + + counter = 0 + result = 0 + rest_operator = [] + rest_digits = [] + check = False + # look for priority operators + for operator in operators: + format_operator = operator.replace(' ', '') + + if format_operator == '/' or format_operator == '*' or format_operator == '//' or format_operator == '%' \ + or format_operator == '**': + first_parameter = digits[counter] + if check: + first_parameter = rest_digits[-1] + if format_operator == '*': + result = arithmetic.multiply(first_parameter, digits[counter + 1]) + elif format_operator == '/': + result = arithmetic.division(first_parameter, digits[counter + 1]) + if type(result) is str: + return result + elif format_operator == '//': + result = arithmetic.integer_division(first_parameter, digits[counter + 1]) + elif format_operator == '%': + result = arithmetic.modulo_division(first_parameter, digits[counter + 1]) + elif format_operator == '**': + result = arithmetic.power(first_parameter, digits[counter + 1]) + if counter != 0: + rest_digits[-1] = result + else: + rest_digits.append(result) + check = True + else: + rest_operator.append(format_operator) + if counter == 0: + rest_digits.append(digits[counter]) + rest_digits.append(digits[counter + 1]) + check = False + counter += 1 + if len(rest_operator) == 0: + # return value + if len(rest_digits) > 0: + return rest_digits[0] + else: + return value + else: + result = rest_digits[0] + counter2 = 0 + for operator in rest_operator: + format_operator = operator.replace(' ', '') + if format_operator == '+': + result = arithmetic.add(result, rest_digits[counter2 + 1]) + elif format_operator == '-': + result = arithmetic.subtraction(result, rest_digits[counter2 + 1]) + counter2 += 1 + return result diff --git a/final_task/pycalc/calculate_math_parameters.py b/final_task/pycalc/calculate_math_parameters.py new file mode 100644 index 00000000..608ac695 --- /dev/null +++ b/final_task/pycalc/calculate_math_parameters.py @@ -0,0 +1,82 @@ +import math +import re +import builtins +from pycalc import calculate_expression, parse_brackets + +math_param = dir(math) +additional_param = ['abs', 'round'] +all_parameters = math_param + additional_param + + +def calc_math(name, value): + if value.find(',') == -1: + result = getattr(math, name)( + float(calculate_expression.calculate("".join(parse_brackets.parse_brackets(value))))) + else: + new_value = value.split(',') + result = getattr(math, name)( + float(calculate_expression.calculate("".join(parse_brackets.parse_brackets(new_value[0])))), + float(calculate_expression.calculate("".join(parse_brackets.parse_brackets(new_value[1]))))) + return result + + +def cal_additional_parameters(name, value): + return getattr(builtins, name)(float(eval(value))) + + +# input: value - string expression +# output: string with calculated parameters +def calculate_math_parameters(value): + value = value.replace('pi', str(math.pi)).replace('e', str(math.e)) + + math_parameters_from_expression = re.findall(r'(\w+)\s*\((.+)\)', value) + value = value.replace(' (', '(') + + for items in math_parameters_from_expression: + new_item_name = items[0] + new_item_value = items[1] + if new_item_name not in all_parameters: + return 'Error: parameter "' + new_item_name + '" not found' + if items[0] in additional_param: + value = value.replace(items[0] + '(' + items[1] + ')', + str(cal_additional_parameters(new_item_name, new_item_value))) + else: + value = value.replace(items[0] + '(' + items[1] + ')', str(calc_math(new_item_name, new_item_value))) + + return value + + +def calc_math_parameter(value): + + result = [] + temp = "" + previous_element = "" + for item in value: + if re.match(r'[a-z]', item) and not re.match(r'[a-z]', previous_element): + if len(temp) > 0: + result.append(temp) + temp = "" + temp += item + if item == ')': + if len(temp) > 0: + if temp.find('(') != -1 and temp.find(')') != -1: + count_left_bracket = re.findall(r'\(', temp) + count_right_bracket = re.findall(r'\)', temp) + if len(count_left_bracket) == len(count_right_bracket): + if len(result) > 0: + if result[-1].find('(') != -1: + temp = result[-1] + str(calculate_math_parameters(temp)) + del result[-1] + else: + temp = str(calculate_math_parameters(temp)) + result.append(temp) + temp = "" + else: + temp = str(calculate_math_parameters(temp)) + result.append(temp) + temp = "" + else: + result.append(temp) + temp = "" + previous_element = item + return result diff --git a/final_task/pycalc/parse_brackets.py b/final_task/pycalc/parse_brackets.py new file mode 100644 index 00000000..2ad0a1d0 --- /dev/null +++ b/final_task/pycalc/parse_brackets.py @@ -0,0 +1,43 @@ +from pycalc import calculate_expression + + +def parse_brackets(value): + result = [] + temp = "" + is_calculate_expression = False + counter_value = 1 + for item in value: + if item == '(' or item == ')': + if item == ')': + temp += item + if len(temp) > 0: + if temp.find('(') != -1 and temp.find(')') != -1: + temp = temp.replace('(', '').replace(')', '') + if len(result) > 0: + if result[-1].find('(') != -1: + temp = result[-1] + str(calculate_expression.calculate(temp)) + del result[-1] + else: + temp = str(calculate_expression.calculate(temp)) + result.append(temp) + temp = "" + is_calculate_expression = True + else: + temp = str(calculate_expression.calculate(temp)) + result.append(temp) + else: + result.append(temp) + temp = "" + else: + if len(value) == counter_value: + temp += item + result.append(temp) + temp += item + if item == ')' and not is_calculate_expression: + temp = "" + elif is_calculate_expression: + temp = temp[:-1] + is_calculate_expression = False + counter_value += 1 + result = ''.join(result) + return result diff --git a/final_task/pycalc/pycalc.py b/final_task/pycalc/pycalc.py new file mode 100644 index 00000000..3e03fe3e --- /dev/null +++ b/final_task/pycalc/pycalc.py @@ -0,0 +1,90 @@ +import argparse +# import re +from pycalc.pycalc_common import pcalc + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("EXPRESSION", type=str, help="expression is the string you use here") + parser.add_argument("-m", "--use-modules", help="additional modules to use", action="store_true") + args = parser.parse_args() + if args.EXPRESSION: + print(pcalc(args.EXPRESSION)) + +# print(pcalc('round(123.4567890)')) +# print(type(pycalc_common.pcalc('-13'))) +# print(pycalc_common.pcalc('sin(e**log(e**e**sin(23.0),45.0) + cos(3.0+log10(e**-e)))')) +# def pcalc(value): +# left_bracket = re.findall(r'\(', value) +# right_bracket = re.findall(r'\)', value) +# if len(left_bracket) != len(right_bracket): +# return 'error: missing bracket' +# +# result_calculate = calculate_math_parameters.calculate_math_parameters(value) +# +# print('result_calculate', result_calculate) +# if len(left_bracket) or len(right_bracket): +# result = parse_brackets.parse_brackets(result_calculate) +# else: +# result = eval(value) +# # print('eval_result:', eval(value)) +# print('my_result:', result) +# return result + + +# print(pcalc('sin(e**log(e**e**sin(23.0),45.0) + cos(3.0+log10(e**-e)))')) +# print(sin(e**log(e**e**sin(23.0),45.0) + cos(3.0+log10(e**-e)))) +# print(calculate_expression.calculate('2.718281828459045**2.718281828459045**-0.8462204041751706')) +# print(2.718281828459045**2.718281828459045**-0.8462204041751706) +# print(2.718281828459045**-0.8462204041751706) +# print(2.718281828459045**0.4290334443756452) +# print(calculate_expression.calculate('5**2')) +# print(calc_math('sin(-cos(-sin(3.0)-cos(-sin(-3.0*5.0)-sin(cos(log10(43.0))))+cos(sin(sin(34.0-2.0**2.0))))--cos(1.0)--cos(0.0)**3.0)')) +# print(sin(-cos(-sin(3.0)-cos(-sin(-3.0*5.0)-sin(cos(log10(43.0))))+cos(sin(sin(34.0-2.0**2.0))))--cos(1.0)--cos(0.0)**3.0)) +# print(parse_brackets.parse_brackets('sin(e**log(e**e**sin(23.0),45.0) + cos(3.0+log10(e**-e)))')) +# print(calculate_math_parameters.calculate_math_parameters('e + .3 + e ')) +# print(pcalc('7+((4+e) + log(8)*8)/cos((log(8) - 4)*2)')) +# +# def calculate(value): +# parameters_level_one = ['**'] +# parameters_level_two = ['/', '*', '//', '%'] +# parameters_level_three = ['+', '-'] +# all_parameters = parameters_level_one + parameters_level_two + parameters_level_three +# # get_numbers = [] +# # get_operators = [] +# # temp = "" +# # prev_item = "" +# # value = value.replace(' ', '') +# # for item in value: +# # if re.match(r'\d', item): +# # get_number.append('item') +# # if not re.match(r'\d]', item): +# operators = re.findall(r'(\D*[^.?\d?])', value) +# digits = re.findall(r'(\.*\d+\.*\d*)', value) +# counter = 0 +# get_first_number = 0 +# get_second_number = 0 +# for item in operators: +# item = item.replace(' ', '') +# if len(digits) > counter: +# get_first_number = digits[counter] +# if len(digits) > counter + 1: +# get_second_number = digits[counter + 1] +# if item not in all_parameters: +# minus = re.findall('-', item) +# +# elements = re.findall(r'[^-+\s]', item) +# print(len(minus) % 2) +# if len(minus) % 2 == 0: +# get_second_number = '-' + get_second_number +# print('elements:', elements) +# if len(minus) == 0: +# return "Error: not accessible operator '" + item + "'" +# get_parameter = re.findall(r'(\D*[^-+.?\d?])', value) +# counter += 1 +# print(get_first_number) +# print(get_second_number) +# print('result:', float(get_first_number) * float(get_second_number)) +# +# print(operators) +# print(digits) diff --git a/final_task/pycalc/pycalc_common.py b/final_task/pycalc/pycalc_common.py new file mode 100644 index 00000000..6e62a9f7 --- /dev/null +++ b/final_task/pycalc/pycalc_common.py @@ -0,0 +1,19 @@ +import re +from pycalc import calculate_math_parameters, calculate_expression, parse_brackets +import math + + +def pcalc(value): + value = value.replace('pi', str(math.pi)).replace('e', str(math.e)) + left_bracket = re.findall(r'\(', value) + right_bracket = re.findall(r'\)', value) + if len(left_bracket) != len(right_bracket): + return 'error: missing bracket' + + math_parameters_from_expression = re.findall(r'(\w+)\s*\((.+)\)', value) + result = value + if len(math_parameters_from_expression): + result = "".join(calculate_math_parameters.calc_math_parameter(value)) + result = parse_brackets.parse_brackets(result) + result = calculate_expression.calculate(result) + return float(result) diff --git a/final_task/setup.py b/final_task/setup.py index e69de29b..7f9954c2 100644 --- a/final_task/setup.py +++ b/final_task/setup.py @@ -0,0 +1,24 @@ +import setuptools + +with open("README.md", "r") as fh: + long_description = fh.read() + +setuptools.setup( + name='pycalc', + version='1.31', + + author="Maxim Tsyba", + author_email="maksimtsuba@gmail.com", + description="Calculator for EPAM", + long_description=long_description, + long_description_content_type="text/markdown", + url="https://github.com/javatechy/dokr", + packages=setuptools.find_packages(include=['pycalc']), + entry_points={'console_scripts': ['pycalc = pycalc.pycalc:main']}, + py_modules=["pycalc"], + classifiers=[ + "Programming Language :: Python :: 3.6", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + ], +)