후위 표기식과 각 피연산자에 대응하는 값들이 주어져 있을 때, 그 식을 계산하는 프로그램을 작성하시오.
첫째 줄에 피연산자의 개수(1 ≤ N ≤ 26) 가 주어진다. 그리고 둘째 줄에는 후위 표기식이 주어진다. (여기서 피연산자는 A~Z의 영대문자이며, A부터 순서대로 N개의 영대문자만이 사용되며, 길이는 100을 넘지 않는다) 그리고 셋째 줄부터 N+2번째 줄까지는 각 피연산자에 대응하는 값이 주어진다. 3번째 줄에는 A에 해당하는 값, 4번째 줄에는 B에 해당하는값 , 5번째 줄에는 C ...이 주어진다, 그리고 피연산자에 대응 하는 값은 100보다 작거나 같은 자연수이다.
후위 표기식을 앞에서부터 계산했을 때, 식의 결과와 중간 결과가 -20억보다 크거나 같고, 20억보다 작거나 같은 입력만 주어진다.
계산 결과를 소숫점 둘째 자리까지 출력한다.
5
ABC*+DE/-
1
2
3
4
5
6.20
import sys
class Node:
def __init__(self, data):
self.data = data
self.next = None
class Stack:
def __init__(self, mathematical_expression):
self.top_node = None
self.mathematical_expression = mathematical_expression
self.alphabet_dict = {chr(alpha): 0 for alpha in range(ord('A'), ord('Z')+1)}
def make_alphabet_dict(self, alphabet):
self.alphabet_dict[chr(alphabet)] = int(sys.stdin.readline().rstrip())
@staticmethod
def elementary_arithmetic(number1, number2, data):
match data:
case '+':
return number1 + number2
case '-':
return number1 - number2
case '*':
return number1 * number2
case '/':
if number2:
return number1 / number2
raise ZeroDivisionError
case _:
raise TypeError
def calculate_mathematical_expression(self):
for char in self.mathematical_expression:
if char.isalpha():
new_node = Node(self.alphabet_dict[char])
if self.top_node:
new_node.next = self.top_node
self.top_node = new_node
else:
number2 = self.top_node.data
number1 = self.top_node.next.data
self.top_node = self.top_node.next.next
new_node = Node(Stack.elementary_arithmetic(number1, number2, char))
if self.top_node:
new_node.next = self.top_node
self.top_node = new_node
return self.top_node.data
def main():
number = int(sys.stdin.readline().rstrip())
mathematical_expression = sys.stdin.readline().rstrip()
new_stack = Stack(mathematical_expression)
start_alphabet = ord('A')
for num in range(number):
new_stack.make_alphabet_dict(start_alphabet)
start_alphabet += 1
print("{:.2f}".format(new_stack.calculate_mathematical_expression()))
if __name__ == '__main__':
main()
단순한 stack 문제라고 생각해서 바로 구현. @staticmethod도 써보고 range(ord('A'), ord('Z')+1)도 해봄.
- 스택 구현은 파이썬 내장 list 사용 고려
- 입력값을 float으로 읽고 처리
- 예외 처리를 좀 더 견고하게 할 수 있음
- 필요하다면 match ~ case 대신 딕셔너리 매핑을 쓰거나, 단순 if-elif를 쓰는 방식도 유지 보수성이 좋을 수 있습니다.
import sys
def main():
input = sys.stdin.readline
# 1) 피연산자 개수 입력
N = int(input().strip())
# 2) 후위 표기식(문자열) 입력
expression = input().strip()
# 3) 알파벳-값 매핑 딕셔너리 생성
values = {}
for i in range(N):
# A부터 차례대로 값 입력받아 float로 저장
alpha = chr(ord('A') + i)
values[alpha] = float(input().strip())
# 4) 스택(파이썬 리스트 사용) 초기화
stack = []
# 5) 후위 표기식 순회하며 계산
for char in expression:
if char.isalpha():
# 피연산자면 스택에 push
stack.append(values[char])
else:
# 연산자면 스택에서 2개 pop 후 계산
b = stack.pop()
a = stack.pop()
# match-case 문 (파이썬 3.10+)
match char:
case '+':
stack.append(a + b)
case '-':
stack.append(a - b)
case '*':
stack.append(a * b)
case '/':
# 0으로 나누는 경우 예외 처리(필요 시)
if b == 0:
raise ZeroDivisionError("0으로 나눌 수 없습니다.")
stack.append(a / b)
case _:
raise TypeError(f"알 수 없는 연산자: {char}")
# 6) 스택에 남은 결과(마지막 값) 가져오기
result = stack.pop()
# 7) 소숫점 둘째 자리까지 출력 (반올림)
print(f"{result:.2f}")
if __name__ == "__main__":
main()