ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 12. 스택과 후위 표기법, 파이썬
    Python/파이썬 자료구조 알고리듬 2019. 6. 6. 15:14
    반응형

    우리가 흔히 사용하는 방식은 중위 표기법(infix notation)인데, 
    연산 기호를 중간에 넣습니다. 
    ex) 1 + 2

     

    연산기호가 앞에 오는 전위 표기법(prefix notation)도 있고..
    ex) + 1 2 

     

    연산기호가 뒤에 오는 후위 표기법(postfix notation)도 있습니다..
    ex) 1 2 +

     

    전위 표기법은 폴란드식 표기법(PN, Polish Notation),
    후위 표기법은 역 폴란드식 표기법(RPN, Reverse-Polish Notation)이라고도 하는데요.
    이런 표기법들은 괄호를 쓸 필요가 없고,
    또 스택으로 구현할 수 있습니다. 

     

    자세한 건 글 마지막 링크들을 참고하시고요. 
    간단하게 느낌만 살펴보도록 하겠습니다.

    후위표기법 :
    5 6 + 7 * 2 /

    중위표기법 :
    ((5 + 6) * 7) / 2
    5 3 2 * +
    5 + 3 * 2

     

    간단한 구현을 위해 조건을 설정하겠습니다. 

    한 자리의 정수와 사칙 연산 기호로만 구성된 후위 표기식을 계산하는 함수를 작성하시오. (띄어 쓰지 않습니다.)
    예) 56+7*2/

     

    [힌트]

    더보기

    하나씩 스택에 저장하다가 연산 기호를 만나면 두 번 팝, 한 번 푸쉬하면 됩니다.

    팝할 때 순서에 주의하시고요. 

     

    def postfix(expression):
        stack = []
        for element in expression:
            if element == '+':
                op2 = stack.pop()
                op1 = stack.pop()
                stack.append(op1 + op2)
            elif element == '-':
                op2 = stack.pop()
                op1 = stack.pop()
                stack.append(op1 - op2)
            elif element == '*':
                op2 = stack.pop()
                op1 = stack.pop()
                stack.append(op1 * op2)
            elif element == '/':
                op2 = stack.pop()
                op1 = stack.pop()
                stack.append(op1 / op2)
            else:
                stack.append(int(element))
        return stack.pop()
    
    
    print(postfix('82/3-3*'))  # 3.0

    operand : 피연산자

     

    프로그래머는 겹치는 부분이 있는 걸 싫어하니까
    이렇게 코딩할 수도 있겠죠.. 

    (두 번 팝한다는 의미로 pop_pop이라고 함수명을 지었습니다.)

    def postfix(expression):
        stack = []
        for element in expression:
            if element == '+':
                op2, op1 = pop_pop(stack)
                stack.append(op1 + op2)
            elif element == '-':
                op2, op1 = pop_pop(stack)
                stack.append(op1 - op2)
            elif element == '*':
                op2, op1 = pop_pop(stack)
                stack.append(op1 * op2)
            elif element == '/':
                op2, op1 = pop_pop(stack)
                stack.append(op1 / op2)
            else:
                stack.append(int(element))
        return stack.pop()
    
    
    def pop_pop(stack):
        op2 = stack.pop()
        op1 = stack.pop()
        return op2, op1
    
    
    print(postfix('82/3-3*'))  # 3.0

     

     

    실제로 사용할 정도가 되려면, 
    숫자의 제한이 없어져야 하고,
    띄어쓰기로 항목들을 나눌 수 있어야 합니다. 
    실수형도 쓸 건지 고려해야 겠구요.
    아무래도 실수형을 못 쓴다면 계산기라고 하긴 어렵겠죠?

     

    더 공부하고 싶으신 분들은 도전해 보시길..

     

    위키들...

    폴란드 표기법
    https://ko.wikipedia.org/wiki/%ED%8F%B4%EB%9E%80%EB%93%9C_%ED%91%9C%EA%B8%B0%EB%B2%95

     

    수식 트리를 이용한 혼합 계산
    https://namu.wiki/w/%ED%98%BC%ED%95%A9%20%EA%B3%84%EC%82%B0#s-3.2

     

    프로그래밍 언어 - 포스

    스택과 후위 표기법으로 무장한 포쓰~라는 프로그래밍 언어도 있었습니다. 

    https://forth-standard.org/

    https://namu.wiki/w/Forth

    https://ko.wikipedia.org/wiki/%ED%8F%AC%EC%8A%A4_(%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D_%EC%96%B8%EC%96%B4)

    포스는 어셈블러에 비해 프로그램을 비교적 쉽게 작성할 수 있는 좋은 타협이며 놀랄 만큼 작은 메모리를 사용하고 놀랄만큼 빠르다. 내장된 컴파일러와 인터프리터를 가지고 동시적인 스레드를 갖는 애플리케이션 코드까지 만드는데 몇 킬로 바이트의 메모리와 어셈블러의 1/2 속도를 내는 시스템을 만든 적이 있다. 

    출처: https://toyfab.tistory.com/entry/What-is-Forth-포스란-무엇이냐 [토이팹]

    https://www.notion.so/Forth-3d1c8ab80b0841a0b3415da9716ee1ba

    https://www.notion.so/4-2-cb84c57dd7d642fcb64d6a08d5768539

    반응형
Designed by Tistory.