[Python] 후위표기법(postifx) 계산 코드

2022. 5. 12. 16:15·Python/Python
반응형

후위표기법(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를 이용한 비동기 방법
  • [Python] DTO, Dataclass Validate 방법
  • Python 에서 go 함수 사용 하는 방법
  • [Python] __new__ method
상쾌한기분
상쾌한기분
  • 상쾌한기분
    상쾌한기분
    상쾌한기분
  • 전체
    오늘
    어제
    • 분류 전체보기 (251)
      • Python (44)
        • Python (26)
        • Django (6)
        • Flask (4)
        • Open Source (6)
      • Kotlin & Java (5)
        • Spring (2)
        • 프로젝트 (1)
      • Go (11)
      • Database (24)
        • MySQL (21)
        • Redis (3)
      • Infrastructure (2)
        • CDC (4)
        • Kafka (5)
        • Prometheus (2)
        • Fluentd (11)
        • Docker (1)
        • Airflow (2)
        • VPN (2)
      • IT (26)
        • AI (9)
        • Langchain (8)
        • Web (18)
        • Git (8)
        • 리팩토링 (9)
        • Micro Service Architecture (8)
        • Clean Code (16)
        • Design Pattern (0)
        • 수학 (1)
        • 알고리즘 (14)
      • OS (14)
        • Centos (10)
        • Ubuntu (3)
        • Mac (1)
      • Search Engine (2)
        • ElasticSearch (1)
        • Lucene Solr (1)
      • PHP (2)
        • Laravel (1)
        • Codeigniter (1)
  • 블로그 메뉴

    • Github 방문
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    CDC
    오블완
    티스토리챌린지
    fluentd
    http
    백준
    Kafka
    performance
    git
    MYSQL
    python
    Langchain
    파이썬
    Golang
    ollama
    docker
    Redis
    prompt
    LLM
    go
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
상쾌한기분
[Python] 후위표기법(postifx) 계산 코드
상단으로

티스토리툴바