From ac11952d42ddd2041bc4aec74306107fd548e80c Mon Sep 17 00:00:00 2001 From: Efim Alekseevich Date: Mon, 3 Dec 2018 16:33:27 +0300 Subject: [PATCH 1/7] working version 2.0 - - --- final_task/calc/__init__.py | 0 final_task/calc/main.py | 16 +++ final_task/calc/main_functions.py | 114 +++++++++++++++ final_task/calc/math_functions.py | 137 ++++++++++++++++++ final_task/calc/other_functions.py | 219 +++++++++++++++++++++++++++++ final_task/setup.py | 26 ++++ 6 files changed, 512 insertions(+) create mode 100644 final_task/calc/__init__.py create mode 100644 final_task/calc/main.py create mode 100644 final_task/calc/main_functions.py create mode 100644 final_task/calc/math_functions.py create mode 100644 final_task/calc/other_functions.py diff --git a/final_task/calc/__init__.py b/final_task/calc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/final_task/calc/main.py b/final_task/calc/main.py new file mode 100644 index 0000000..9d3fe86 --- /dev/null +++ b/final_task/calc/main.py @@ -0,0 +1,16 @@ +import argparse +from calc.main_functions import reduction_expression, compare + + +def main(): + try: + + parser = argparse.ArgumentParser(description='Takes mathematical expression') + parser.add_argument('string') + s = parser.parse_args().string + lis = reduction_expression(s) + print(compare(lis)) + + except Exception: + print('ERROR: Unknown exit') + exit() diff --git a/final_task/calc/main_functions.py b/final_task/calc/main_functions.py new file mode 100644 index 0000000..d3a5d46 --- /dev/null +++ b/final_task/calc/main_functions.py @@ -0,0 +1,114 @@ +import calc.other_functions as o_f +from calc.math_functions import decide_func + + +def reduction_expression(s): + + lis = o_f.finding_elements(s) + lis = o_f.additions(lis) + return lis + + +def compare(lis): + i = 0 + while i < len(lis)-1: + if lis[i] == '==': + a, b = cut(i, lis) + return a == b + elif lis[i] == '<=': + a, b = cut(i, lis) + return a <= b + elif lis[i] == '>=': + a, b = cut(i, lis) + return a >= b + elif lis[i] == '!=': + a, b = cut(i, lis) + return a != b + elif lis[i] == '>': + a, b = cut(i, lis) + return a > b + elif lis[i] == '<': + a, b = cut(i, lis) + return a < b + + i += 1 + + return decide_expression(lis) + + +def cut(i, lis): + a = decide_expression(lis[:i]) + b = decide_expression(lis[i+1:]) + return a, b + + +def decide_expression(s): + s.insert(0, '(') + s.append(')') + st_nums = [] + st_ops = [] + i = 0 + + while i < len(s): + verify(s, i, st_nums, st_ops) + i += 1 + + if len(st_nums) > 1 or len(st_ops): + print('ERROR: not necessary operation') + exit() + + return st_nums[0] + + +def verify(s, i, st_nums, st_ops): + + if type(s[i]) == float: + st_nums.append(s[i]) + + elif s[i] == '(': + st_ops.append('(') + if o_f.prior(s[i+1]) == 1: + st_nums.append(0) + + elif s[i] == ')': + if st_ops[-1] == '(': + del st_ops[-1] + else: + try: + st_nums[-2] = o_f.bin_operate(st_nums[-2], st_nums[-1], st_ops[-1]) + except Exception: + print('ERROR: not necessary element') + exit() + del st_ops[-1] + del st_nums[-1] + verify(s, i, st_nums, st_ops) + + elif o_f.prior(s[i]) == 5: + args = o_f.decide_function(i, s) + ready_args = decide_args(args) + s[i] = decide_func(s[i], ready_args) + verify(s, i, st_nums, st_ops) + + elif o_f.prior(s[i]) <= o_f.prior(st_ops[-1]): + if s[i] == '^' and st_ops[-1] == '^': + st_ops.append(s[i]) + else: + try: + st_nums[-2] = o_f.bin_operate(st_nums[-2], st_nums[-1], st_ops[-1]) + except Exception: + print('ERROR: not necessary element') + exit() + del st_nums[-1] + del st_ops[-1] + verify(s, i, st_nums, st_ops) + + elif o_f.prior(s[i]) > o_f.prior(st_ops[-1]): + st_ops.append(s[i]) + + +def decide_args(args): + ready_args = [] + for s in args: + ready_args.append(decide_expression(s)) + + return ready_args diff --git a/final_task/calc/math_functions.py b/final_task/calc/math_functions.py new file mode 100644 index 0000000..ec2c04e --- /dev/null +++ b/final_task/calc/math_functions.py @@ -0,0 +1,137 @@ +from math import * + + +def decide_func(func, ready_args): + if len(ready_args) == 0: + print('ERROR: no necessary arguments ') + exit() + + elif len(ready_args) > 2: + print('ERROR: so many arguments') + exit() + + elif func == 'abs': + return abs(ready_args[0]) + + elif func == 'acos': + return acos(ready_args[0]) + + elif func == 'acosh': + return acosh(ready_args[0]) + + elif func == 'asin': + return asin(ready_args[0]) + + elif func == 'asinh': + return asinh(ready_args[0]) + + elif func == 'atan': + return atan(ready_args[0]) + + elif func == 'atanh': + return atanh(ready_args[0]) + + elif func == 'ceil': + return ceil(ready_args[0]) + + elif func == 'cos': + return cos(ready_args[0]) + + elif func == 'degrees': + return degrees(ready_args[0]) + + elif func == 'erf': + return erf(ready_args[0]) + + elif func == 'exp': + return exp(ready_args[0]) + + elif func == 'expm1': + return expm1(ready_args[0]) + + elif func == 'fabs': + return fabs(ready_args[0]) + + elif func == 'factorial': + return factorial(ready_args[0]) + + elif func == 'floor': + return floor(ready_args[0]) + + elif func == 'frexp': + return frexp(ready_args[0]) + + elif func == 'gamma': + return gamma(ready_args[0]) + + elif func == 'lgamma': + return lgamma(ready_args[0]) + + elif func == 'log10': + return log10(ready_args[0]) + + elif func == 'log1p': + return log1p(ready_args[0]) + + elif func == 'log2': + return log2(ready_args[0]) + + elif func == 'radians': + return radians(ready_args[0]) + + elif func == 'sin': + return sin(ready_args[0]) + + elif func == 'sinh': + return sinh(ready_args[0]) + + elif func == 'sqrt': + return sqrt(ready_args[0]) + + elif func == 'tan': + return tan(ready_args[0]) + + elif func == 'tanh': + return tanh(ready_args[0]) + + elif func == 'trunc': + return trunc(ready_args[0]) + + elif func == 'round': + if len(ready_args) == 1: + ready_args.append(0) + return round(ready_args[0], int(ready_args[1])) + + elif func == 'log': + if len(ready_args) == 1: + ready_args.append(e) + return log(ready_args[0], ready_args[1]) + + elif len(ready_args) < 2: + print('ERROR: no necessary arguments or our function "' + s[i] + '"') + exit() + + elif func == 'atan2': + return atan2(ready_args[0], ready_args[1]) + + elif func == 'fmod': + return fmod(ready_args[0], ready_args[1]) + + elif func == 'gcd': + return gcd(ready_args[0], ready_args[1]) + + elif func == 'hypot': + return hypot(ready_args[0], ready_args[1]) + + elif func == 'copysign': + return copysign(ready_args[0], ready_args[1]) + + elif func == 'pow': + return pow(ready_args[0], ready_args[1]) + + elif func == 'ldexp': + return ldexp(ready_args[0], ready_args[1]) + + else: + print('ERROR: not find function "' + func + '"') + exit() diff --git a/final_task/calc/other_functions.py b/final_task/calc/other_functions.py new file mode 100644 index 0000000..edc2fdb --- /dev/null +++ b/final_task/calc/other_functions.py @@ -0,0 +1,219 @@ +def finding_elements(s): + lis = [] + unit_num = '' + unit_fun = '' + s += ' ' + i = 0 + while i < len(s): + + if 96 < ord(s[i]) < 122: + if unit_num: + unit_num = verify_num(unit_num) + lis.append(unit_num) + unit_num = '' + unit_fun += s[i] + unit_fun = verify_pi_e(unit_fun, lis) + + elif (47 < ord(s[i]) < 58) or s[i] == '.': + if unit_fun: + lis.append(unit_fun) + unit_fun = '' + unit_num += s[i] + + else: + if unit_num: + unit_num = verify_num(unit_num) + lis.append(unit_num) + unit_num = '' + if unit_fun: + lis.append(unit_fun) + unit_fun = '' + lis.append(s[i]) + + i += 1 + return lis + + +def verify_num(str_num): + try: + float_num = float(str_num) + return float_num + except Exception: + print('ERROR: incorrect value "' + str_num + '"') + exit() + + +def verify_pi_e(unit_func, lis): + if unit_func == 'e': + lis.append(2.718281828459045) + return '' + elif unit_func == 'pi': + lis.append(3.141592653589793) + return '' + else: + return unit_func + + +def additions(lis): + i = 0 + while i < len(lis)-1: + if lis[i] == '/' and lis[i+1] == '/': + lis[i] = '//' + del lis[i+1] + + elif lis[i] == 'expm' and lis[i+1] == 1: + lis[i] = 'expm1' + del lis[i+1] + + elif lis[i] == 'atan' and lis[i+1] == 2: + lis[i] = 'atan2' + del lis[i+1] + + elif lis[i] == 'log': + if lis[i+1] == 10: + lis[i] = 'log10' + del lis[i+1] + elif lis[i+1] == 2: + lis[i] = 'log2' + del lis[i+1] + + elif lis[i] == '=' and lis[i+1] != '=': + del lis[i] + lis[i-1] += '=' + continue + + elif type(lis[i]) == float: + if prior(lis[i + 1]) == 5 or lis[i + 1] == '(': + lis.insert(i + 1, '*') + elif lis[i] == ')': + if lis[i + 1] == '(' or prior(lis[i + 1]) == 5: + lis.insert(i + 1, '*') + + i += 1 + + i = 0 + while i < len(lis) - 1: + + if prior(lis[i]) == 1 and prior(lis[i+1]) == 1: + if lis[i] != lis[i+1]: + lis[i] = '-' + else: + lis[i] = '+' + del lis[i+1] + continue + + elif type(lis[i]) == float: + if (prior(lis[i + 1]) == 5 or lis[i + 1] == '(') and type(lis[i + 1]) != float: + lis.insert(i + 1, '*') + elif lis[i] == ')': + if lis[i + 1] == '(' or prior(lis[i + 1]) == 5: + lis.insert(i + 1, '*') + + elif (prior(lis[i]) == 2 or prior(lis[i]) == 3) and prior(lis[i+1]) == 1: + del lis[i+1] + lis[i+1] *= -1 + continue + + elif lis[i] == ' ': + del lis[i] + continue + + if lis[i+1] == ' ': + del lis[i+1] + continue + + i += 1 + + return lis + + +def prior(op): + four_4 = [',', ' ', '<', '>', '=', '!', '>=', '<=', '==', '!='] + if op == '(' or op == ')': + return 0 + elif op == '+' or op == '-': + return 1 + elif op == '/' or op == '*' or op == '//' or op == '%': + return 2 + elif op == '^': + return 3 + elif op in four_4: + return 4 + else: + return 5 + + +def bin_operate(a, b, op): + if op == '+': + return a + b + elif op == '-': + return a - b + elif op == '*': + return a * b + elif op == '%': + return a % b + elif op == '^': + return a ** b + elif op == '/': + if b != 0: + return a / b + else: + print('ERROR: divide by zero') + exit() + elif op == '//': + if b != 0: + return a // b + else: + print('ERROR: divide by zero') + exit() + else: + print('ERROR: unknown operator "' + op + '"') + exit() + + +def decide_function(i, s): + + line = get_line_args(i, s) + args = get_args(line) + return args + + +def get_line_args(i, s): + hooks = 1 + i = i + 1 + if s[i] != '(': + print('ERROR: arguments of function "' + s[i-1] + '" should be between hooks') + exit() + line = [s[i]] + del s[i] + + while hooks != 0 and i < len(s): + if s[i] == '(': + hooks += 1 + elif s[i] == ')': + hooks -= 1 + line.append(s[i]) + del s[i] + + return line + + +def get_args(line): + + args = [] + h = 0 + arg = [] + + for i in line[1:-1]: + if i == ',' and h == 0: + args.append(arg) + arg = [] + else: + arg.append(i) + if i == '(': + h += 1 + elif i == ')': + h -= 1 + if arg: + args.append(arg) + return args diff --git a/final_task/setup.py b/final_task/setup.py index e69de29..f44b5ba 100644 --- a/final_task/setup.py +++ b/final_task/setup.py @@ -0,0 +1,26 @@ +from setuptools import setup, find_packages + +setup( + name='pycalc', + version='2.0', + description='Decide different expressions', + long_description='No fake', + classifiers=[ + 'Development Status :: Beta test', + 'License :: None :: None', + 'Programming Language :: Python :: 3.6', + ], + keywords='calculator', + url='not add', + author='Efi-fi', + author_email='efimprostopro@gmail.com', + license='None', + packages=find_packages(), + install_requires=[], + include_package_data=True, + zip_safe=False, + entry_points={ + 'console_scripts': + ['pycalc = calc.main:main'] + } + ) From 01846e5e1f86e800ca7352af7802a7f2a5d5a3f9 Mon Sep 17 00:00:00 2001 From: Efim Alekseevich Date: Tue, 4 Dec 2018 15:30:20 +0300 Subject: [PATCH 2/7] adding unit_tests --- final_task/calc/unit_tests.py | 85 +++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 final_task/calc/unit_tests.py diff --git a/final_task/calc/unit_tests.py b/final_task/calc/unit_tests.py new file mode 100644 index 0000000..462dc55 --- /dev/null +++ b/final_task/calc/unit_tests.py @@ -0,0 +1,85 @@ +import unittest + +from calc.other_functions import * +from calc.main_functions import * + + +class TestFindingElements(unittest.TestCase): + """Test for function 'finding_elements' from other_functions.py""" + + def test1_fe1(self): + formated_expression = finding_elements('3 >= 5') + self.assertEqual(formated_expression, [3, ' ', '>', '=', ' ', 5, ' ']) + + def test2_fe2(self): + formated_expression = finding_elements('3.234') + self.assertEqual(formated_expression, [3.234, ' ']) + + def test3_fe3(self): + formated_expression = finding_elements('epi') + self.assertEqual(formated_expression, [2.718281828459045, 3.141592653589793, ' ']) + + def test4_fe4(self): + formated_expression = finding_elements('log()') + self.assertEqual(formated_expression, ['log', '(', ')', ' ']) + + +class TestAdditions(unittest.TestCase): + """Test for function 'additions' from other_functions.py""" + + def test5_ad1(self): + formated_expression = additions([3, ' ', '>', '=', ' ', 5, ' ']) + self.assertEqual(formated_expression, [3, '>=', 5]) + + def test6_ad2(self): + formated_expression = additions([3.234, ' ']) + self.assertEqual(formated_expression, [3.234]) + + def test7_ad3(self): + formated_expression = additions([2.718281828459045, 3.141592653589793, ' ']) + self.assertEqual(formated_expression, [2.718281828459045, '*', 3.141592653589793]) + + def test8_ad4(self): + formated_expression = additions(['log', '(', ')', ' ']) + self.assertEqual(formated_expression, ['log', '(', ')']) + + def test9_ad5(self): + formated_expression = additions(['log', 10, '(', ')', ' ']) + self.assertEqual(formated_expression, ['log10', '(', ')']) + + def test10_ad6(self): + formated_expression = additions([' ', '-', '+', '-', '-']) + self.assertEqual(formated_expression, ['-']) + + +class TestGetLineArgs(unittest.TestCase): + """Test for function 'get_line_args' from other_functions.py""" + + def test11_gl1(self): + formated_expression = get_line_args(6, [0, 1, 2, 3, 4, 5, 'log', '(', 2, '*', '(', ')', 4, ')', ')', '(', ')']) + self.assertEqual(formated_expression, ['(', 2, '*', '(', ')', 4, ')']) + + +class TestGetArgs(unittest.TestCase): + """Test for function 'get_args' from other_functions.py""" + + def test12_ga1(self): + formated_expression = get_args(['(', 2, '*', '(', ')', 4, ')']) + self.assertEqual(formated_expression, [[2, '*', '(', ')', 4]]) + + def test13_ga2(self): + """Few arguments""" + + formated_expression = get_args(['(', '(', 2, ')', ',', 4, ',', '(', ')', ')']) + self.assertEqual(formated_expression, [['(', 2, ')'], [4], ['(', ')']]) + + def test14_ga3(self): + """Function in function""" + + formated_expression = get_args(['(', 'log', '(', 2, ',', 2, ')', ',', 4, ')']) + self.assertEqual(formated_expression, [['log', '(', 2, ',', 2, ')'], [4]]) + + + + +unittest.main() From 415dfb9d1aed02b1298a44b94e64af6d5042318a Mon Sep 17 00:00:00 2001 From: Efim Alekseevich Date: Tue, 4 Dec 2018 15:55:40 +0300 Subject: [PATCH 3/7] fix unit_tests --- final_task/calc/unit_tests.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/final_task/calc/unit_tests.py b/final_task/calc/unit_tests.py index 462dc55..e28ae6c 100644 --- a/final_task/calc/unit_tests.py +++ b/final_task/calc/unit_tests.py @@ -1,7 +1,6 @@ import unittest from calc.other_functions import * -from calc.main_functions import * class TestFindingElements(unittest.TestCase): @@ -80,6 +79,4 @@ def test14_ga3(self): self.assertEqual(formated_expression, [['log', '(', 2, ',', 2, ')'], [4]]) - - unittest.main() From c312ad6d83ec55229c75aecdfbd11b3554730dc3 Mon Sep 17 00:00:00 2001 From: Efim Alekseevich Date: Tue, 4 Dec 2018 16:19:05 +0300 Subject: [PATCH 4/7] fix unit_tests: delete running --- final_task/calc/unit_tests.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/final_task/calc/unit_tests.py b/final_task/calc/unit_tests.py index e28ae6c..384b8c4 100644 --- a/final_task/calc/unit_tests.py +++ b/final_task/calc/unit_tests.py @@ -77,6 +77,3 @@ def test14_ga3(self): formated_expression = get_args(['(', 'log', '(', 2, ',', 2, ')', ',', 4, ')']) self.assertEqual(formated_expression, [['log', '(', 2, ',', 2, ')'], [4]]) - - -unittest.main() From e0325f14c8296c2e5d8de79a7c85f35a84936e84 Mon Sep 17 00:00:00 2001 From: Efim Alekseevich Date: Wed, 5 Dec 2018 01:01:36 +0300 Subject: [PATCH 5/7] add some unittests --- final_task/calc/unit_tests.py | 51 +++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/final_task/calc/unit_tests.py b/final_task/calc/unit_tests.py index 384b8c4..c823196 100644 --- a/final_task/calc/unit_tests.py +++ b/final_task/calc/unit_tests.py @@ -1,6 +1,7 @@ import unittest from calc.other_functions import * +from calc.math_functions import decide_func class TestFindingElements(unittest.TestCase): @@ -77,3 +78,53 @@ def test14_ga3(self): formated_expression = get_args(['(', 'log', '(', 2, ',', 2, ')', ',', 4, ')']) self.assertEqual(formated_expression, [['log', '(', 2, ',', 2, ')'], [4]]) + + +class TestMiniFunctions1(unittest.TestCase): + """Test for minifunction from other_functions.py""" + + def test15_vn(self): + """Function 'verify_num' verify performance""" + + formated_expression = verify_num('12.3456') + self.assertEqual(formated_expression, 12.3456) + + def test16_pe1(self): + """Function 'verify_pi_e' verify performance""" + + formated_expression = verify_pi_e('pi', []) + self.assertEqual(formated_expression, '') + + def test17_pe2(self): + """Function 'verify_pi_e' verify performance""" + + formated_expression = verify_pi_e('pow', []) + self.assertEqual(formated_expression, 'pow') + + def test18_pr1(self): + """Function 'prior' verify performance""" + + formated_expression = prior(12.34) + self.assertEqual(formated_expression, 5) + + def test19_pr2(self): + """Function 'prior' verify performance""" + + formated_expression = prior('log') + self.assertEqual(formated_expression, 5) + + def test20_bo(self): + """Function 'bin_operate' verify performance""" + + formated_expression = bin_operate(2, 2, '^') + self.assertEqual(formated_expression, 4) + + +class TestDecideFunction(unittest.TestCase): + """Test for function 'decide_function' from math_functions.py""" + + def test21_mdf(self): + """verify performance""" + + formated_expression = decide_func('pow', [2, 2]) + self.assertEqual(formated_expression, 4) From ce8c04f5c359f476fd184237ec12fc2bc7628666 Mon Sep 17 00:00:00 2001 From: Efim Alekseevich Date: Tue, 18 Dec 2018 15:35:55 +0300 Subject: [PATCH 6/7] correction of defects --- final_task/calc/main.py | 13 +-- final_task/calc/main_functions.py | 86 +++++++------- final_task/calc/math_functions.py | 181 +++++++---------------------- final_task/calc/other_functions.py | 46 +++++--- final_task/calc/unit_tests.py | 48 ++++---- 5 files changed, 145 insertions(+), 229 deletions(-) diff --git a/final_task/calc/main.py b/final_task/calc/main.py index 9d3fe86..b97bbc0 100644 --- a/final_task/calc/main.py +++ b/final_task/calc/main.py @@ -1,16 +1,13 @@ import argparse -from calc.main_functions import reduction_expression, compare +from calc.main_functions import reduction_expression, check_compared def main(): try: - parser = argparse.ArgumentParser(description='Takes mathematical expression') parser.add_argument('string') s = parser.parse_args().string - lis = reduction_expression(s) - print(compare(lis)) - - except Exception: - print('ERROR: Unknown exit') - exit() + composition = reduction_expression(s) + print(check_compared(composition)) + except Exception as e: + print('ERROR: ', e) diff --git a/final_task/calc/main_functions.py b/final_task/calc/main_functions.py index d3a5d46..adafbfd 100644 --- a/final_task/calc/main_functions.py +++ b/final_task/calc/main_functions.py @@ -1,39 +1,42 @@ -import calc.other_functions as o_f +from calc import other_functions from calc.math_functions import decide_func -def reduction_expression(s): +class ExpressionError(Exception): + pass - lis = o_f.finding_elements(s) - lis = o_f.additions(lis) + +def reduction_expression(string): + lis = other_functions.finding_elements(string) + lis = other_functions.additions(lis) return lis -def compare(lis): +def check_compared(composition): i = 0 - while i < len(lis)-1: - if lis[i] == '==': - a, b = cut(i, lis) + while i < len(composition)-1: + if composition[i] == '==': + a, b = cut(i, composition) return a == b - elif lis[i] == '<=': - a, b = cut(i, lis) + elif composition[i] == '<=': + a, b = cut(i, composition) return a <= b - elif lis[i] == '>=': - a, b = cut(i, lis) + elif composition[i] == '>=': + a, b = cut(i, composition) return a >= b - elif lis[i] == '!=': - a, b = cut(i, lis) + elif composition[i] == '!=': + a, b = cut(i, composition) return a != b - elif lis[i] == '>': - a, b = cut(i, lis) + elif composition[i] == '>': + a, b = cut(i, composition) return a > b - elif lis[i] == '<': - a, b = cut(i, lis) + elif composition[i] == '<': + a, b = cut(i, composition) return a < b i += 1 - return decide_expression(lis) + return decide_expression(composition) def cut(i, lis): @@ -55,55 +58,54 @@ def decide_expression(s): if len(st_nums) > 1 or len(st_ops): print('ERROR: not necessary operation') - exit() + raise ExpressionError return st_nums[0] -def verify(s, i, st_nums, st_ops): - - if type(s[i]) == float: - st_nums.append(s[i]) +def verify(string, index, st_nums, st_ops): + if type(string[index]) == float: + st_nums.append(string[index]) - elif s[i] == '(': + elif string[index] == '(': st_ops.append('(') - if o_f.prior(s[i+1]) == 1: + if other_functions.get_prior(string[index+1]) == 1: st_nums.append(0) - elif s[i] == ')': + elif string[index] == ')': if st_ops[-1] == '(': del st_ops[-1] else: try: - st_nums[-2] = o_f.bin_operate(st_nums[-2], st_nums[-1], st_ops[-1]) + st_nums[-2] = other_functions.perform_bin_operate(st_nums[-2], st_nums[-1], st_ops[-1]) except Exception: print('ERROR: not necessary element') - exit() + raise ExpressionError del st_ops[-1] del st_nums[-1] - verify(s, i, st_nums, st_ops) + verify(string, index, st_nums, st_ops) - elif o_f.prior(s[i]) == 5: - args = o_f.decide_function(i, s) + elif other_functions.get_prior(string[index]) == 5: + args = other_functions.decide_function(index, string) ready_args = decide_args(args) - s[i] = decide_func(s[i], ready_args) - verify(s, i, st_nums, st_ops) + string[index] = decide_func(string[index], ready_args) + verify(string, index, st_nums, st_ops) - elif o_f.prior(s[i]) <= o_f.prior(st_ops[-1]): - if s[i] == '^' and st_ops[-1] == '^': - st_ops.append(s[i]) + elif other_functions.get_prior(string[index]) <= other_functions.get_prior(st_ops[-1]): + if string[index] == '^' and st_ops[-1] == '^': + st_ops.append(string[index]) else: try: - st_nums[-2] = o_f.bin_operate(st_nums[-2], st_nums[-1], st_ops[-1]) + st_nums[-2] = other_functions.perform_bin_operate(st_nums[-2], st_nums[-1], st_ops[-1]) except Exception: print('ERROR: not necessary element') - exit() + raise ExpressionError del st_nums[-1] del st_ops[-1] - verify(s, i, st_nums, st_ops) + verify(string, index, st_nums, st_ops) - elif o_f.prior(s[i]) > o_f.prior(st_ops[-1]): - st_ops.append(s[i]) + elif other_functions.get_prior(string[index]) > other_functions.get_prior(st_ops[-1]): + st_ops.append(string[index]) def decide_args(args): diff --git a/final_task/calc/math_functions.py b/final_task/calc/math_functions.py index ec2c04e..52a8b2d 100644 --- a/final_task/calc/math_functions.py +++ b/final_task/calc/math_functions.py @@ -1,137 +1,44 @@ -from math import * - - -def decide_func(func, ready_args): - if len(ready_args) == 0: - print('ERROR: no necessary arguments ') - exit() - - elif len(ready_args) > 2: - print('ERROR: so many arguments') - exit() - - elif func == 'abs': - return abs(ready_args[0]) - - elif func == 'acos': - return acos(ready_args[0]) - - elif func == 'acosh': - return acosh(ready_args[0]) - - elif func == 'asin': - return asin(ready_args[0]) - - elif func == 'asinh': - return asinh(ready_args[0]) - - elif func == 'atan': - return atan(ready_args[0]) - - elif func == 'atanh': - return atanh(ready_args[0]) - - elif func == 'ceil': - return ceil(ready_args[0]) - - elif func == 'cos': - return cos(ready_args[0]) - - elif func == 'degrees': - return degrees(ready_args[0]) - - elif func == 'erf': - return erf(ready_args[0]) - - elif func == 'exp': - return exp(ready_args[0]) - - elif func == 'expm1': - return expm1(ready_args[0]) - - elif func == 'fabs': - return fabs(ready_args[0]) - - elif func == 'factorial': - return factorial(ready_args[0]) - - elif func == 'floor': - return floor(ready_args[0]) - - elif func == 'frexp': - return frexp(ready_args[0]) - - elif func == 'gamma': - return gamma(ready_args[0]) - - elif func == 'lgamma': - return lgamma(ready_args[0]) - - elif func == 'log10': - return log10(ready_args[0]) - - elif func == 'log1p': - return log1p(ready_args[0]) - - elif func == 'log2': - return log2(ready_args[0]) - - elif func == 'radians': - return radians(ready_args[0]) - - elif func == 'sin': - return sin(ready_args[0]) - - elif func == 'sinh': - return sinh(ready_args[0]) - - elif func == 'sqrt': - return sqrt(ready_args[0]) - - elif func == 'tan': - return tan(ready_args[0]) - - elif func == 'tanh': - return tanh(ready_args[0]) - - elif func == 'trunc': - return trunc(ready_args[0]) - - elif func == 'round': - if len(ready_args) == 1: - ready_args.append(0) - return round(ready_args[0], int(ready_args[1])) - - elif func == 'log': - if len(ready_args) == 1: - ready_args.append(e) - return log(ready_args[0], ready_args[1]) - - elif len(ready_args) < 2: - print('ERROR: no necessary arguments or our function "' + s[i] + '"') - exit() - - elif func == 'atan2': - return atan2(ready_args[0], ready_args[1]) - - elif func == 'fmod': - return fmod(ready_args[0], ready_args[1]) - - elif func == 'gcd': - return gcd(ready_args[0], ready_args[1]) - - elif func == 'hypot': - return hypot(ready_args[0], ready_args[1]) - - elif func == 'copysign': - return copysign(ready_args[0], ready_args[1]) - - elif func == 'pow': - return pow(ready_args[0], ready_args[1]) - - elif func == 'ldexp': - return ldexp(ready_args[0], ready_args[1]) - - else: - print('ERROR: not find function "' + func + '"') - exit() +import math + + +functions_mapping = { + 'abs': math.fabs, + 'acos': math.acos, + 'acosh': math.acosh, + 'asin': math.asin, + 'asinh': math.asinh, + 'atan': math.atan, + 'atanh': math.atanh, + 'ceil': math.ceil, + 'cos': math.cos, + 'degrees': math.degrees, + 'exp': math.exp, + 'expm1': math.expm1, + 'fabs': math.fabs, + 'factorial': math.factorial, + 'log10': math.log10, + 'log2': math.log2, + 'radians': math.radians, + 'sin': math.sin, + 'round': round, + 'log': math.log, + 'pow': math.pow, +} + + +def decide_func(function, ready_args): + for name, func in functions_mapping.items(): + if function == name: + try: + if len(ready_args) == 1: + return float(func(ready_args[0])) + elif len(ready_args) == 2: + return float(func(ready_args[0], ready_args[1])) + else: + print('ERROR: problem with arguments in function "' + function + '"!') + exit() + except Exception: + print('ERROR: problem with arguments in function "' + function + '"!') + exit() + print('ERROR: not find function "' + function + '"!') + exit() diff --git a/final_task/calc/other_functions.py b/final_task/calc/other_functions.py index edc2fdb..ede8e43 100644 --- a/final_task/calc/other_functions.py +++ b/final_task/calc/other_functions.py @@ -1,24 +1,30 @@ +from math import pi, e, tau + + def finding_elements(s): lis = [] + ord_a = 97 + ord_z = 122 + ord_0 = 48 + ord_9 = 57 unit_num = '' unit_fun = '' s += ' ' - i = 0 - while i < len(s): + for element in s: - if 96 < ord(s[i]) < 122: + if ord_a <= ord(element) <= ord_z: if unit_num: unit_num = verify_num(unit_num) lis.append(unit_num) unit_num = '' - unit_fun += s[i] + unit_fun += element unit_fun = verify_pi_e(unit_fun, lis) - elif (47 < ord(s[i]) < 58) or s[i] == '.': + elif (ord_0 <= ord(element) <= ord_9) or element == '.': if unit_fun: lis.append(unit_fun) unit_fun = '' - unit_num += s[i] + unit_num += element else: if unit_num: @@ -28,9 +34,8 @@ def finding_elements(s): if unit_fun: lis.append(unit_fun) unit_fun = '' - lis.append(s[i]) + lis.append(element) - i += 1 return lis @@ -45,10 +50,13 @@ def verify_num(str_num): def verify_pi_e(unit_func, lis): if unit_func == 'e': - lis.append(2.718281828459045) + lis.append(e) return '' elif unit_func == 'pi': - lis.append(3.141592653589793) + lis.append(pi) + return '' + elif unit_func == 'tau': + lis.append(tau) return '' else: return unit_func @@ -83,10 +91,10 @@ def additions(lis): continue elif type(lis[i]) == float: - if prior(lis[i + 1]) == 5 or lis[i + 1] == '(': + if get_prior(lis[i + 1]) == 5 or lis[i + 1] == '(': lis.insert(i + 1, '*') elif lis[i] == ')': - if lis[i + 1] == '(' or prior(lis[i + 1]) == 5: + if lis[i + 1] == '(' or get_prior(lis[i + 1]) == 5: lis.insert(i + 1, '*') i += 1 @@ -94,7 +102,7 @@ def additions(lis): i = 0 while i < len(lis) - 1: - if prior(lis[i]) == 1 and prior(lis[i+1]) == 1: + if get_prior(lis[i]) == 1 and get_prior(lis[i+1]) == 1: if lis[i] != lis[i+1]: lis[i] = '-' else: @@ -103,13 +111,13 @@ def additions(lis): continue elif type(lis[i]) == float: - if (prior(lis[i + 1]) == 5 or lis[i + 1] == '(') and type(lis[i + 1]) != float: + if (get_prior(lis[i + 1]) == 5 or lis[i + 1] == '(') and type(lis[i + 1]) != float: lis.insert(i + 1, '*') elif lis[i] == ')': - if lis[i + 1] == '(' or prior(lis[i + 1]) == 5: + if lis[i + 1] == '(' or get_prior(lis[i + 1]) == 5: lis.insert(i + 1, '*') - elif (prior(lis[i]) == 2 or prior(lis[i]) == 3) and prior(lis[i+1]) == 1: + elif (get_prior(lis[i]) == 2 or get_prior(lis[i]) == 3) and get_prior(lis[i+1]) == 1: del lis[i+1] lis[i+1] *= -1 continue @@ -127,7 +135,7 @@ def additions(lis): return lis -def prior(op): +def get_prior(op): four_4 = [',', ' ', '<', '>', '=', '!', '>=', '<=', '==', '!='] if op == '(' or op == ')': return 0 @@ -143,7 +151,7 @@ def prior(op): return 5 -def bin_operate(a, b, op): +def perform_bin_operate(a, b, op): if op == '+': return a + b elif op == '-': @@ -182,7 +190,7 @@ def get_line_args(i, s): hooks = 1 i = i + 1 if s[i] != '(': - print('ERROR: arguments of function "' + s[i-1] + '" should be between hooks') + print('ERROR: arguments of function "' + str(s[i-1]) + '" should be between hooks') exit() line = [s[i]] del s[i] diff --git a/final_task/calc/unit_tests.py b/final_task/calc/unit_tests.py index c823196..681f4f8 100644 --- a/final_task/calc/unit_tests.py +++ b/final_task/calc/unit_tests.py @@ -7,19 +7,19 @@ class TestFindingElements(unittest.TestCase): """Test for function 'finding_elements' from other_functions.py""" - def test1_fe1(self): + def test_fe1(self): formated_expression = finding_elements('3 >= 5') self.assertEqual(formated_expression, [3, ' ', '>', '=', ' ', 5, ' ']) - def test2_fe2(self): + def test_fe2(self): formated_expression = finding_elements('3.234') self.assertEqual(formated_expression, [3.234, ' ']) - def test3_fe3(self): + def test_fe3(self): formated_expression = finding_elements('epi') self.assertEqual(formated_expression, [2.718281828459045, 3.141592653589793, ' ']) - def test4_fe4(self): + def test_fe4(self): formated_expression = finding_elements('log()') self.assertEqual(formated_expression, ['log', '(', ')', ' ']) @@ -27,27 +27,27 @@ def test4_fe4(self): class TestAdditions(unittest.TestCase): """Test for function 'additions' from other_functions.py""" - def test5_ad1(self): + def test_ad1(self): formated_expression = additions([3, ' ', '>', '=', ' ', 5, ' ']) self.assertEqual(formated_expression, [3, '>=', 5]) - def test6_ad2(self): + def test_ad2(self): formated_expression = additions([3.234, ' ']) self.assertEqual(formated_expression, [3.234]) - def test7_ad3(self): + def test_ad3(self): formated_expression = additions([2.718281828459045, 3.141592653589793, ' ']) self.assertEqual(formated_expression, [2.718281828459045, '*', 3.141592653589793]) - def test8_ad4(self): + def test_ad4(self): formated_expression = additions(['log', '(', ')', ' ']) self.assertEqual(formated_expression, ['log', '(', ')']) - def test9_ad5(self): + def test_ad5(self): formated_expression = additions(['log', 10, '(', ')', ' ']) self.assertEqual(formated_expression, ['log10', '(', ')']) - def test10_ad6(self): + def test_ad6(self): formated_expression = additions([' ', '-', '+', '-', '-']) self.assertEqual(formated_expression, ['-']) @@ -55,7 +55,7 @@ def test10_ad6(self): class TestGetLineArgs(unittest.TestCase): """Test for function 'get_line_args' from other_functions.py""" - def test11_gl1(self): + def test_gl1(self): formated_expression = get_line_args(6, [0, 1, 2, 3, 4, 5, 'log', '(', 2, '*', '(', ')', 4, ')', ')', '(', ')']) self.assertEqual(formated_expression, ['(', 2, '*', '(', ')', 4, ')']) @@ -63,17 +63,17 @@ def test11_gl1(self): class TestGetArgs(unittest.TestCase): """Test for function 'get_args' from other_functions.py""" - def test12_ga1(self): + def test_ga1(self): formated_expression = get_args(['(', 2, '*', '(', ')', 4, ')']) self.assertEqual(formated_expression, [[2, '*', '(', ')', 4]]) - def test13_ga2(self): + def test_ga2(self): """Few arguments""" formated_expression = get_args(['(', '(', 2, ')', ',', 4, ',', '(', ')', ')']) self.assertEqual(formated_expression, [['(', 2, ')'], [4], ['(', ')']]) - def test14_ga3(self): + def test_ga3(self): """Function in function""" formated_expression = get_args(['(', 'log', '(', 2, ',', 2, ')', ',', 4, ')']) @@ -83,37 +83,37 @@ def test14_ga3(self): class TestMiniFunctions1(unittest.TestCase): """Test for minifunction from other_functions.py""" - def test15_vn(self): + def test_vn(self): """Function 'verify_num' verify performance""" formated_expression = verify_num('12.3456') self.assertEqual(formated_expression, 12.3456) - def test16_pe1(self): + def test_pe1(self): """Function 'verify_pi_e' verify performance""" formated_expression = verify_pi_e('pi', []) self.assertEqual(formated_expression, '') - def test17_pe2(self): + def test_pe2(self): """Function 'verify_pi_e' verify performance""" formated_expression = verify_pi_e('pow', []) self.assertEqual(formated_expression, 'pow') - def test18_pr1(self): + def test_pr1(self): """Function 'prior' verify performance""" - formated_expression = prior(12.34) + formated_expression = get_prior(12.34) self.assertEqual(formated_expression, 5) - def test19_pr2(self): + def test_pr2(self): """Function 'prior' verify performance""" - formated_expression = prior('log') + formated_expression = get_prior('log') self.assertEqual(formated_expression, 5) - def test20_bo(self): + def test_bo(self): """Function 'bin_operate' verify performance""" formated_expression = bin_operate(2, 2, '^') @@ -123,8 +123,10 @@ def test20_bo(self): class TestDecideFunction(unittest.TestCase): """Test for function 'decide_function' from math_functions.py""" - def test21_mdf(self): + def test_mdf(self): """verify performance""" formated_expression = decide_func('pow', [2, 2]) self.assertEqual(formated_expression, 4) + +unittest.main() \ No newline at end of file From b842ccffe8845cc5d26932d0c9c3ad1d0009e0ca Mon Sep 17 00:00:00 2001 From: Efim Alekseevich Date: Tue, 18 Dec 2018 15:52:21 +0300 Subject: [PATCH 7/7] fiX bags in tests --- final_task/calc/unit_tests.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/final_task/calc/unit_tests.py b/final_task/calc/unit_tests.py index 681f4f8..4a531c4 100644 --- a/final_task/calc/unit_tests.py +++ b/final_task/calc/unit_tests.py @@ -1,5 +1,4 @@ import unittest - from calc.other_functions import * from calc.math_functions import decide_func @@ -116,7 +115,7 @@ def test_pr2(self): def test_bo(self): """Function 'bin_operate' verify performance""" - formated_expression = bin_operate(2, 2, '^') + formated_expression = perform_bin_operate(2, 2, '^') self.assertEqual(formated_expression, 4) @@ -128,5 +127,3 @@ def test_mdf(self): formated_expression = decide_func('pow', [2, 2]) self.assertEqual(formated_expression, 4) - -unittest.main() \ No newline at end of file