728x90
반응형
후위표기법(postfix) 계산 코드
from typing import List, Optional
class Profit(object):
__slots__ = ['subject_name', 'profit_value']
def __init__(self, subject_name: str, profit_value: float):
self.subject_name = subject_name
self.profit_value = profit_value
def find_profit_by_subject_name(profits: List[Profit], subject_name: str) -> Optional[Profit]:
for p in profits:
if p.subject_name == subject_name:
return p
return None
class PostfixBase:
__slots__ = ['subject_formula', ]
operations = ["*", "/", "+", "-"]
operations_priority = { "*": 3, "/": 3, "+": 2, "-": 2, "(": 1 }
calculations = {
"*": lambda x, y: x * y,
"/": lambda x, y: x / y,
"+": lambda x, y: x + y,
"-": lambda x, y: x - y,
}
def __init__(self, subject_formula: str):
self.subject_formula = subject_formula
class PostfixConverter(PostfixBase):
def convert_formula_to_list(self) -> list:
res = []
before, after = 0, 0
for i, f in enumerate(self.subject_formula):
if f in self.operations:
res.append(self.subject_formula[before:after + 1])
res.append(f)
before = i + 1
else:
after = i
if i == len(self.subject_formula) - 1:
res.append(self.subject_formula[before:after + 1])
print(res)
return res
def convert_formula_list_to_postfix(self):
formula_list = self.convert_formula_to_list()
stack, res = [], []
for f in formula_list:
if f not in self.operations:
res.append(f)
elif f == "(":
stack.append(f)
elif f == ")":
while stack != [] and stack[-1] != "(":
res.append(stack.pop())
stack.pop()
else:
while stack != [] and self.operations_priority[stack[-1]] >= self.operations_priority[f]:
res.append(stack.pop())
stack.append(f)
while stack:
res.append(stack.pop())
print(res)
return res
class PostfixCalculator(PostfixBase):
def __init__(self, subject_formula: str):
super().__init__(subject_formula)
self.postfix_converter = PostfixConverter(subject_formula)
def calculate(self):
postfix_formula = self.postfix_converter.convert_formula_list_to_postfix()
stack = []
for p in postfix_formula:
if p not in self.operations:
profit = find_profit_by_subject_name(profits, p)
if profit:
stack.append(profit.profit_value)
else:
if p.isdigit():
stack.append(float(p))
else:
# subject not found case
stack.append(1.0)
else:
value1, value2 = stack.pop(), stack.pop()
# print(value1, p, value2)
if p == "/" and (value1 == 0 or value2 == 0):
raise Exception("can't divide zero")
stack.append(self.calculations[p](value2, value1))
return stack.pop()
################################################################################################################################
profits = [
Profit("Product costs", 10.0),
Profit("Sales revenue", 1.0),
Profit("Marketing", 1.1),
Profit("PG commission", 2.0),
]
subject_formulas = [
"1-Product costs/Sales revenue",
"Marketing+PG commission+Labor costs(D)+Internal fee+Service fee_external+Packing material"
]
for formula in subject_formulas:
calculator = PostfixCalculator(formula)
value = calculator.calculate()
print(value)
['1', '-', 'Product costs', '/', 'Sales revenue']
['1', 'Product costs', 'Sales revenue', '/', '-']
-9.0
['Marketing', '+', 'PG commission', '+', 'Labor costs(D)', '+', 'Internal fee', '+', 'Service fee_external', '+', 'Packing material']
['Marketing', 'PG commission', '+', 'Labor costs(D)', '+', 'Internal fee', '+', 'Service fee_external', '+', 'Packing material', '+']
7.1
728x90
반응형
'Python > Python' 카테고리의 다른 글
[Python] Thread와 Async를 이용한 비동기 방법 (0) | 2022.07.09 |
---|---|
[Python] DTO, Dataclass Validate 방법 (0) | 2022.07.08 |
Python 에서 go 함수 사용 하는 방법 (0) | 2022.02.05 |
[Python] __new__ method (0) | 2021.12.23 |
[Python] 파이썬 multiprocessing (0) | 2021.11.25 |