Skip to content

Instantly share code, notes, and snippets.

@melborne
Created June 18, 2012 15:23
Show Gist options
  • Save melborne/2948894 to your computer and use it in GitHub Desktop.
Save melborne/2948894 to your computer and use it in GitHub Desktop.
RPN
class RPN
def self.run(exp)
res = tokenize(exp).inject([]) { |m, token| m << evaluate(token, m) }
raise(ArgumentError, "expression is not completed") unless res.size==1
res.first
end
def self.tokenize(s)
s.split
end
def self.evaluate(token, m)
basic_operators = /^[+\/-]|\*{1,2}$/
number = /^[\d.]+$/
case token
when basic_operators
m.pop(2).inject($&)
when 'ln'
Math.log(m.pop)
when 'sum'
m.inject(:+).tap{ m.clear }
when number
$&.to_f
else
raise ArgumentError, "operator `#{token}` not defined"
end
end
private_class_method :tokenize, :evaluate
end
if __FILE__ == $0
RPN.run("3 4 +") # => 7.0
RPN.run("3 4 + 5.5 *") # => 38.5
RPN.run("3 4 + 5 * 6 7 / -") # => 34.142857142857146
RPN.run("3 4 **") # => 81.0
RPN.run("2.7 ln") # => 0.9932517730102834
RPN.run("1 2 3 4 5 sum 5 /") # => 3.0
end
require_relative "rpn"
describe RPN do
describe "run" do
it "raise operation error" do
->{ RPN.run("2 3 %") }.should raise_error(ArgumentError, 'operator `%` not defined')
end
it "raise expression error" do
->{ RPN.run("2 3 4 *") }.should raise_error(ArgumentError, 'expression is not completed')
end
it "calc plus" do
RPN.run("2 3 +").should eql 5.0
end
it "calc plus-multi" do
RPN.run("4 2 3 + *").should eql 20.0
end
it "calc plus-multi-minus" do
RPN.run("10 4 3 + 2 * -").should eql -4.0
end
it "calc plus-multi-minus-plus" do
RPN.run("34 12 33 55 66 + * - +").should eql -3947.0
end
it "calc minus" do
RPN.run("90 3.8 -").should eql 86.2
end
it "calc divide" do
RPN.run("90 3.8 /").should eql 90/3.8
end
it "calc exponential" do
RPN.run("3 4 **").should eql 3**4.0
end
it "calc log" do
RPN.run("2.7 ln").should eql Math.log(2.7)
end
it "calc sum" do
RPN.run("10 10 10 10 sum 4 /").should eql 10.0
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment