Skip to content

Instantly share code, notes, and snippets.

@kosmatov
Created July 20, 2012 03:42
Show Gist options
  • Save kosmatov/3148509 to your computer and use it in GitHub Desktop.
Save kosmatov/3148509 to your computer and use it in GitHub Desktop.
Calculator
require 'sort_station'
station = SortStation.new(ARGV[0].to_s)
puts station.expr.join(' ')
@proc_stack = []
station.expr.each do |op|
if op.is_a?(Float)
@proc_stack << op
else
operand1 = @proc_stack.pop
operand2 = @proc_stack.pop
res = operator2.send op, operator1
@proc_stack << res
end
end
puts @proc_stack.pop
$ ruby calc.rb "(12 + 64.5 * 2) / 8 * (90 + 23 * 7)"
12.0 64.5 2.0 * + 8.0 / 90.0 23.0 7.0 * + *
4423.875
class SortStation
attr_accessor :expr
def op_preced(op)
return 3 if ['*', '/', '%'].include?(op)
return 2 if ['+', '-'].include?(op)
0
end
def operator?(val)
return ['*', '/', '%', '+', '-'].include?(val)
end
def operand?(val)
return val == '0' || val == '.' || val.to_i != 0
end
def last_op_to_output_stack?(last_op, op)
return operator?(last_op) && (op_preced(op) <= op_preced(last_op))
end
def initialize(input_string)
output_stack = []
operand_stack = []
operator_stack = []
input_string.each_char do |sym|
if operand?(sym)
operand_stack << sym
else
if operand_stack.any?
output_stack << operand_stack.join.to_f
operand_stack = []
end
if operator?(sym)
while last_op = operator_stack.pop
if last_op_to_output_stack?(last_op, sym)
output_stack << last_op
else
operator_stack << last_op
break
end
end
operator_stack << sym
elsif sym == '('
operator_stack << sym
elsif sym == ')'
err = true
while last_op = operator_stack.pop
if last_op == '('
err = false
break
else
output_stack << last_op
end
end
raise 'Parentheses mismatched' if err
end
end
end
output_stack << operand_stack.join.to_f if operand_stack.any?
output_stack += operator_stack
self.expr = output_stack
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment