From 6948983ed276e3e5d72a583ef92ddaf3a67f0709 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Mon, 22 Apr 2019 16:17:31 +0300 Subject: [PATCH 1/6] initial commit --- final_task/pycalc/core/calculator.py | 86 ++++++++++++++++++++++ final_task/pycalc/tests/test_calculator.py | 7 ++ 2 files changed, 93 insertions(+) create mode 100644 final_task/pycalc/core/calculator.py create mode 100644 final_task/pycalc/tests/test_calculator.py diff --git a/final_task/pycalc/core/calculator.py b/final_task/pycalc/core/calculator.py new file mode 100644 index 00000000..2d8a8566 --- /dev/null +++ b/final_task/pycalc/core/calculator.py @@ -0,0 +1,86 @@ +'''This module calculate the exception''' +import math + + +def get_priority(operand): + '''Determines the priority of the operation''' + low_priority = ('+', '-') + return 1 if operand in low_priority else 2 + + +def convert_into_rpn(expression): + '''Rewrites the expression into the reverse polish notation''' + arithmetic_operations = ('+', '-', '*', '/', '//', '%', '^') + math_functions = [getattr(math, attr) for attr in dir(math) if callable(getattr(math, attr))] + constants = (math.pi, math.e, math.tau) + stack = [] + num = '' + polish_notation = '' + + # rewriting expression into reverse polish notation + for symbol in expression: + if symbol in arithmetic_operations: + polish_notation += num + ' ' + num = '' + while True: + if not stack: + break + if stack[-1] == '(' or (get_priority(symbol) > get_priority(stack[-1])): + break + elif get_priority(symbol) <= get_priority(stack[-1]): + polish_notation += stack.pop() + stack.append(symbol) + elif symbol.isdigit() or symbol == '.': + num += symbol + elif symbol == '(': + stack.append(symbol) + elif symbol == ')': + polish_notation += num + ' ' + num = '' + while True: + tmp = stack.pop() + if tmp == '(': + break + polish_notation += tmp + ' ' + polish_notation += num + ' ' + while stack: + polish_notation += stack.pop() + ' ' + + return polish_notation + + +def solve(expression): + '''Solves an expression using reverse polish notation.''' + polish_notation = convert_into_rpn(expression) + num = '' + stack = [] + for symbol in polish_notation: + if symbol.isdigit() or symbol == '.': + num += symbol + else: + if num: + stack.append(float(num)) + num = '' + if symbol == '+': + tmp = stack.pop() + stack.pop() + stack.append(tmp) + elif symbol == '-': + lower_element = stack.pop() + upper_element = stack.pop() + stack.append(upper_element - lower_element) + elif symbol == '*': + tmp = stack.pop() * stack.pop() + stack.append(tmp) + elif symbol == '/': + lower_element = stack.pop() + upper_element = stack.pop() + stack.append(upper_element / lower_element) + return stack[0] + + +def main(): + expression = str(input()) + print(solve(expression)) + +if __name__ == "__main__": + main() diff --git a/final_task/pycalc/tests/test_calculator.py b/final_task/pycalc/tests/test_calculator.py new file mode 100644 index 00000000..8ef794f3 --- /dev/null +++ b/final_task/pycalc/tests/test_calculator.py @@ -0,0 +1,7 @@ +import unittest +from PythonHomework.final_task.pycalc.core import calculator + + +class TestCalculator(unittest.TestCase): + def test_solve(self): + self.assertEqual(calculator.solve('110 * 180 +(360 - 200 + (3 - 2))'), 19961.0) From 2330d642932e4dd6b8b171f1738cebf0dda79d55 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Mon, 22 Apr 2019 20:23:44 +0300 Subject: [PATCH 2/6] added main module --- final_task/__init__.py | 0 final_task/pycalc/core/calculator.py | 10 +--------- final_task/pycalc/main.py | 10 ++++++++++ 3 files changed, 11 insertions(+), 9 deletions(-) delete mode 100644 final_task/__init__.py create mode 100644 final_task/pycalc/main.py diff --git a/final_task/__init__.py b/final_task/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/final_task/pycalc/core/calculator.py b/final_task/pycalc/core/calculator.py index 2d8a8566..9aaaf606 100644 --- a/final_task/pycalc/core/calculator.py +++ b/final_task/pycalc/core/calculator.py @@ -1,4 +1,4 @@ -'''This module calculate the exception''' +'''This module calculate the expression''' import math @@ -76,11 +76,3 @@ def solve(expression): upper_element = stack.pop() stack.append(upper_element / lower_element) return stack[0] - - -def main(): - expression = str(input()) - print(solve(expression)) - -if __name__ == "__main__": - main() diff --git a/final_task/pycalc/main.py b/final_task/pycalc/main.py new file mode 100644 index 00000000..c043456a --- /dev/null +++ b/final_task/pycalc/main.py @@ -0,0 +1,10 @@ +from PythonHomework.final_task.pycalc.core.calculator import solve + + +def main(): + expression = str(input()) + print(solve(expression)) + + +if __name__ == '__main__': + main() From d21d88391e51aad7fb7c50f3589d412899df696c Mon Sep 17 00:00:00 2001 From: Vladislav Date: Mon, 22 Apr 2019 22:22:10 +0300 Subject: [PATCH 3/6] code refractor --- final_task/pycalc/core/calculator.py | 54 ++++++++++++++++++---------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/final_task/pycalc/core/calculator.py b/final_task/pycalc/core/calculator.py index 9aaaf606..30d51ac2 100644 --- a/final_task/pycalc/core/calculator.py +++ b/final_task/pycalc/core/calculator.py @@ -8,6 +8,40 @@ def get_priority(operand): return 1 if operand in low_priority else 2 +def handling_operator(polish_notation, num, stack, symbol): + '''if the lexeme is an operator, then: + if it is the last character of the expression, the expression is incorrect; + if this is a unary minus, then add it to the stack; + otherwise: + pushing the top elements of the stack into the result string, while the priority of the current operator is less than or equal to the priority of the operator located on the verine of the stack; + put the current operator in the stack;''' + polish_notation += num + ' ' + while True: + if not stack: + break + if stack[-1] == '(' or (get_priority(symbol) > get_priority(stack[-1])): + break + elif get_priority(symbol) <= get_priority(stack[-1]): + polish_notation += stack.pop() + stack.append(symbol) + + return polish_notation, '' + + +def handling_closing_bracket(polish_notation, num, stack): + '''if the lexeme is a closing bracket, then: + we place elements from the stack into the resulting line until we meet the opening bracket, moreover, the opening bracket is removed from the stack, but not added to the resulting line; + if the function symbol is at the top of the stack, then we put it from the stack into the result string; + if the opening loop was not met, then the brackets are not consistent.''' + polish_notation += num + ' ' + while True: + tmp = stack.pop() + if tmp == '(': + break + polish_notation += tmp + ' ' + + return polish_notation, '' + def convert_into_rpn(expression): '''Rewrites the expression into the reverse polish notation''' arithmetic_operations = ('+', '-', '*', '/', '//', '%', '^') @@ -17,31 +51,15 @@ def convert_into_rpn(expression): num = '' polish_notation = '' - # rewriting expression into reverse polish notation for symbol in expression: if symbol in arithmetic_operations: - polish_notation += num + ' ' - num = '' - while True: - if not stack: - break - if stack[-1] == '(' or (get_priority(symbol) > get_priority(stack[-1])): - break - elif get_priority(symbol) <= get_priority(stack[-1]): - polish_notation += stack.pop() - stack.append(symbol) + polish_notation, num = handling_operator(polish_notation, num, stack, symbol) elif symbol.isdigit() or symbol == '.': num += symbol elif symbol == '(': stack.append(symbol) elif symbol == ')': - polish_notation += num + ' ' - num = '' - while True: - tmp = stack.pop() - if tmp == '(': - break - polish_notation += tmp + ' ' + polish_notation, num = handling_closing_bracket(polish_notation, num, stack) polish_notation += num + ' ' while stack: polish_notation += stack.pop() + ' ' From a913640c5e2b0bb051cc934f102f880847cb5351 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Wed, 24 Apr 2019 20:55:22 +0300 Subject: [PATCH 4/6] code refactor --- final_task/pycalc/core/calculator.py | 30 +++++++++++++--------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/final_task/pycalc/core/calculator.py b/final_task/pycalc/core/calculator.py index 30d51ac2..727bc3f6 100644 --- a/final_task/pycalc/core/calculator.py +++ b/final_task/pycalc/core/calculator.py @@ -1,6 +1,6 @@ '''This module calculate the expression''' import math - +import operator as op def get_priority(operand): '''Determines the priority of the operation''' @@ -69,28 +69,26 @@ def convert_into_rpn(expression): def solve(expression): '''Solves an expression using reverse polish notation.''' + operators = { + '+': op.add, + '-': op.sub, + '*': op.mul, + '/': op.floordiv + } polish_notation = convert_into_rpn(expression) num = '' stack = [] for symbol in polish_notation: if symbol.isdigit() or symbol == '.': num += symbol - else: + elif symbol in operators.keys(): + if num: + stack.append(float(num)) + num = '' + lower_num, upper_num = stack.pop(), stack.pop() + stack.append(operators[symbol](upper_num, lower_num)) + elif not symbol.isdigit(): if num: stack.append(float(num)) num = '' - if symbol == '+': - tmp = stack.pop() + stack.pop() - stack.append(tmp) - elif symbol == '-': - lower_element = stack.pop() - upper_element = stack.pop() - stack.append(upper_element - lower_element) - elif symbol == '*': - tmp = stack.pop() * stack.pop() - stack.append(tmp) - elif symbol == '/': - lower_element = stack.pop() - upper_element = stack.pop() - stack.append(upper_element / lower_element) return stack[0] From c63506e2b0247f69c98f766d782e93c577f97d5d Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 25 Apr 2019 00:53:25 +0300 Subject: [PATCH 5/6] added setup tools --- final_task/pycalc/__init__.py | 0 final_task/pycalc/core/__init__.py | 0 final_task/pycalc/core/calculator.py | 2 ++ final_task/setup.py | 12 ++++++++++++ 4 files changed, 14 insertions(+) create mode 100644 final_task/pycalc/__init__.py create mode 100644 final_task/pycalc/core/__init__.py 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/core/__init__.py b/final_task/pycalc/core/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/final_task/pycalc/core/calculator.py b/final_task/pycalc/core/calculator.py index 727bc3f6..4102832b 100644 --- a/final_task/pycalc/core/calculator.py +++ b/final_task/pycalc/core/calculator.py @@ -2,6 +2,7 @@ import math import operator as op + def get_priority(operand): '''Determines the priority of the operation''' low_priority = ('+', '-') @@ -42,6 +43,7 @@ def handling_closing_bracket(polish_notation, num, stack): return polish_notation, '' + def convert_into_rpn(expression): '''Rewrites the expression into the reverse polish notation''' arithmetic_operations = ('+', '-', '*', '/', '//', '%', '^') diff --git a/final_task/setup.py b/final_task/setup.py index e69de29b..62e61469 100644 --- a/final_task/setup.py +++ b/final_task/setup.py @@ -0,0 +1,12 @@ +'''This is the application installation module.''' +from setuptools import setup, find_packages + +setup( + name='pycalc', + version='1.2', + packages=find_packages(), + py_modules=['main'], + entry_points={ + 'console_scripts': ['pycalc = pycalc.main:main'] + } +) \ No newline at end of file From d302245a56c3b4b25d2966c8c7e156333e67c700 Mon Sep 17 00:00:00 2001 From: Vladislav Date: Thu, 25 Apr 2019 15:49:29 +0300 Subject: [PATCH 6/6] code refactor --- final_task/{pycalc => }/__init__.py | 0 final_task/{pycalc/core => calculator}/__init__.py | 0 final_task/calculator/core/__init__.py | 0 final_task/{pycalc => calculator}/core/calculator.py | 0 final_task/{pycalc => calculator}/main.py | 2 +- final_task/{pycalc => calculator}/tests/test_calculator.py | 0 final_task/setup.py | 2 +- 7 files changed, 2 insertions(+), 2 deletions(-) rename final_task/{pycalc => }/__init__.py (100%) rename final_task/{pycalc/core => calculator}/__init__.py (100%) create mode 100644 final_task/calculator/core/__init__.py rename final_task/{pycalc => calculator}/core/calculator.py (100%) rename final_task/{pycalc => calculator}/main.py (62%) rename final_task/{pycalc => calculator}/tests/test_calculator.py (100%) diff --git a/final_task/pycalc/__init__.py b/final_task/__init__.py similarity index 100% rename from final_task/pycalc/__init__.py rename to final_task/__init__.py diff --git a/final_task/pycalc/core/__init__.py b/final_task/calculator/__init__.py similarity index 100% rename from final_task/pycalc/core/__init__.py rename to final_task/calculator/__init__.py diff --git a/final_task/calculator/core/__init__.py b/final_task/calculator/core/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/final_task/pycalc/core/calculator.py b/final_task/calculator/core/calculator.py similarity index 100% rename from final_task/pycalc/core/calculator.py rename to final_task/calculator/core/calculator.py diff --git a/final_task/pycalc/main.py b/final_task/calculator/main.py similarity index 62% rename from final_task/pycalc/main.py rename to final_task/calculator/main.py index c043456a..7100734c 100644 --- a/final_task/pycalc/main.py +++ b/final_task/calculator/main.py @@ -1,4 +1,4 @@ -from PythonHomework.final_task.pycalc.core.calculator import solve +from core.calculator import solve def main(): diff --git a/final_task/pycalc/tests/test_calculator.py b/final_task/calculator/tests/test_calculator.py similarity index 100% rename from final_task/pycalc/tests/test_calculator.py rename to final_task/calculator/tests/test_calculator.py diff --git a/final_task/setup.py b/final_task/setup.py index 62e61469..e851e6d0 100644 --- a/final_task/setup.py +++ b/final_task/setup.py @@ -3,7 +3,7 @@ setup( name='pycalc', - version='1.2', + version='1.3', packages=find_packages(), py_modules=['main'], entry_points={