Skip to content

Instantly share code, notes, and snippets.

@maekawatoshiki
Created August 9, 2016 13:11
Show Gist options
  • Save maekawatoshiki/e270b51c81115318ab216da2c33f0b80 to your computer and use it in GitHub Desktop.
Save maekawatoshiki/e270b51c81115318ab216da2c33f0b80 to your computer and use it in GitHub Desktop.
calculator
require "std"
module Calc
def prim(input:string):string
str = ""
if input[$pos].alpha? # function (sqrt..)
fname = ""
while input[$pos].alpha?
fname += input[$pos]
$pos += 1
end
$pos += 1 # (
str = addsub(input)
$pos += 1 # )
str + fname + " "
elsif input[$pos] == '('
$pos += 1
str = addsub(input)
$pos += 1
str
else
while input[$pos].digit? | input[$pos] == '.'
str += input[$pos]
$pos += 1
end
str + " "
end
end
def muldiv(input:string):string
str = prim input
while input[$pos] == '*' | input[$pos] == '/' | input[$pos] == '^'
op = input[$pos]
$pos += 1
str += prim(input) + op + " "
end
str
end
def addsub(input:string):string
str = muldiv input
while input[$pos] == '+' | input[$pos] == '-'
op = input[$pos]
$pos += 1
str += muldiv(input) + op + " "
end
str
end
def run(expr:string):double
tok_str = addsub expr
puts "reverse polish: ", tok_str
tok_ary = tok_str.split(' ')
# VM ( calculate )
cur_stack_sz = 256
stack = new cur_stack_sz double
sp = 0
for i in 0...length tok_ary
s = tok_ary[i]
if s == "+"
stack[sp-2] = stack[sp-2] + stack[sp-1]
sp -= 1
elsif s == "-"
stack[sp-2] = stack[sp-2] - stack[sp-1]
sp -= 1
elsif s == "*"
stack[sp-2] = stack[sp-2] * stack[sp-1]
sp -= 1
elsif s == "/"
stack[sp-2] = stack[sp-2] / stack[sp-1]
sp -= 1
elsif s == "^"
stack[sp-2] = Math::pow stack[sp-2], stack[sp-1]
sp -= 1
elsif s == "sqrt"
stack[sp-1] = Math::sqrt stack[sp-1]
else
stack[sp] = s.to_float
sp += 1
end
end
stack[0]
end
end
$pos = 0
print "expression: "
puts Calc::run gets
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment