=begin
수식 트리 만들고 계산하기
후위 수식을 받아서 트리를 만들고 계산한다
중위 수식을 후위 수식으로 변경하는 것은 생략
=end
class ExpTreeNode
attr_accessor :data, :left, :right
def initialize(data)
@data = data
@left = nil
@right = nil
end
end
class ExpTree
OPERATOR_LIST = ['+', '-', '*', '/']
def initialize
@root = nil
end
def load_postfix_expression(exp)
expression = exp.clone
@root = build_expression_tree(expression)
end
def calculate
calculate_recursive(@root)
end
private
def build_expression_tree(exp, parent_node = nil, is_left = nil)
# 표현식이 끝남
return nil if 0 >= exp.length
# 표현식 끝을 토큰으로 가져오고 표현식에서 잘라버림
data = exp.split(//)[exp.length - 1]
exp.chop!
new_node = ExpTreeNode.new(data)
# 부모 노드가 지정된 경우 새 노드를 부모 노드에 붙임
if parent_node
is_left ? parent_node.left = new_node : parent_node.right = new_node
end
# 연산자인 경우 피연산자 두 개를 얻음
if OPERATOR_LIST.include?(data)
new_node.right = build_expression_tree(exp, new_node, nil)
new_node.left = build_expression_tree(exp, new_node, true)
end
# 새 노드 리턴
new_node
end
def calculate_recursive( node )
# 연산자인 경우 피연산자 두 개를 얻어서 계산하고 리턴
if OPERATOR_LIST.include?(node.data)
operand1 = calculate_recursive(node.left)
operand2 = calculate_recursive(node.right)
case node.data
when '+'
result = operand1.to_i + operand2.to_i
when '-'
result = operand1.to_i - operand2.to_i
when '*'
result = operand1.to_i * operand2.to_i
when '/'
result = operand1.to_i / operand2.to_i
end
else
# 피연산자인 경우 자기 자신을 리턴
result = node.data
end
result
end
end
exp_tree = ExpTree.new
exp_tree.load_postfix_expression("12*78-+")
puts exp_tree.calculate
exp_tree.load_postfix_expression("78*58*+2/32--")
puts exp_tree.calculate