Last active
December 20, 2015 01:29
-
-
Save litch/6049233 to your computer and use it in GitHub Desktop.
RPN 3 ways. I had two - then tried to do the pattern-matching solution, wound up being intermediate performance...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'rspec/autorun' | |
require 'benchmark' | |
describe "polish notation" do | |
it "do a trivial case" do | |
polish_parser(:+, 1, 1).first.should == 2 | |
reverse_stack_polish_parser(:+, 1, 1).first.should == 2 | |
pm_polish_parser(:+, 1, 1).first.should == 2 | |
end | |
it "can do two things" do | |
polish_parser(:+, :-, 1, 1, 1).first.should == 1 | |
reverse_stack_polish_parser(:+, :-, 1, 1, 1).first.should == 1 | |
pm_polish_parser(:+, :-, 1, 1, 1).first.should == 1 | |
end | |
it "can do something complex" do | |
polish_parser(:-, :*, :div, 15, :-, 7, :+, 1, 1, 3, :+, 2, :+, 1, 1).first.should == 5 | |
reverse_stack_polish_parser(:-, :*, :div, 15, :-, 7, :+, 1, 1, 3, :+, 2, :+, 1, 1).first.should == 5 | |
pm_polish_parser(:-, :*, :div, 15, :-, 7, :+, 1, 1, 3, :+, 2, :+, 1, 1).first.should == 5 | |
end | |
it "is performant" do | |
Benchmark.bmbm do |results| | |
results.report("reverse_stack") { 100000.times { reverse_stack_polish_parser(:-, :*, :div, 15, :-, 7, :+, 1, 1, 3, :+, 2, :+, 1, 1) }} | |
results.report("recursive") { 100000.times { polish_parser(:-, :*, :div, 15, :-, 7, :+, 1, 1, 3, :+, 2, :+, 1, 1) }} | |
results.report("pattern matched") { 100000.times { pm_polish_parser(:-, :*, :div, 15, :-, 7, :+, 1, 1, 3, :+, 2, :+, 1, 1) }} | |
end | |
end | |
end | |
# Rehearsal --------------------------------------------------- | |
# reverse_stack 0.680000 0.110000 0.790000 ( 0.791758) | |
# recursive 3.210000 0.000000 3.210000 ( 3.212995) | |
# pattern matched 1.770000 0.010000 1.780000 ( 1.774518) | |
# ------------------------------------------ total: 5.780000sec | |
# user system total real | |
# reverse_stack 0.780000 0.420000 1.200000 ( 1.204618) | |
# recursive 3.230000 0.000000 3.230000 ( 3.235451) | |
# pattern matched 1.710000 0.000000 1.710000 ( 1.718585) | |
def pm_polish_parser(*args) | |
if args[0].is_a?(Symbol) && args[1].is_a?(Fixnum) && args[2].is_a?(Fixnum) | |
calc = args[1].send(args[0], args[2]) | |
return calc, *args[3..-1] | |
elsif args[0].is_a?(Symbol) && args[1].is_a?(Fixnum) && args[2].is_a?(Symbol) | |
pm_polish_parser(args[0], args[1], *pm_polish_parser(*args[2..-1])) | |
else | |
pm_polish_parser args[0], *pm_polish_parser(*args[1..-1]) | |
end | |
end | |
def reverse_stack_polish_parser(*args) | |
stack = [] | |
args.reverse_each { |arg| | |
if !arg.is_a? Symbol | |
stack.push(arg) | |
else | |
operand1 = stack.pop | |
operand2 = stack.pop | |
stack.push operand1.send(arg, operand2) | |
end | |
} | |
stack | |
end | |
# RECURSIVE METHOD | |
def polish_parser(*args) | |
if result = match_and_operate(*args) | |
result | |
else | |
second_symbol_index = args[1..-1].find_index{|a| a.is_a? Symbol} | |
saved_args = args[0..second_symbol_index] | |
mutated_args = polish_parser(*args[second_symbol_index+1..-1]) | |
result = polish_parser(*saved_args, *mutated_args) | |
end | |
end | |
def match_and_operate(*args) | |
if args[0].is_a?(Symbol) && args[1].is_a?(Fixnum) && args[2].is_a?(Fixnum) | |
calc = args[1].send(args[0], args[2]) | |
return calc, *args[3..-1] | |
else | |
return false | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment