Skip to content

Instantly share code, notes, and snippets.

@mgaskill
Last active May 23, 2016 05:41
Show Gist options
  • Save mgaskill/96f04e7e1f72a86446f4939ac690759a to your computer and use it in GitHub Desktop.
Save mgaskill/96f04e7e1f72a86446f4939ac690759a to your computer and use it in GitHub Desktop.
Ruby benchmark program for a simple two-operand, one operator expression parser
require 'benchmark'
def match_gaskill(formula)
return [] unless (match = formula.match(/^\s*(-?\d+(?:\.\d+)?)\s*([+\/*-])\s*(-?\d+(?:\.\d+)?)\s*$/))
return [match[1].to_f, match[2], match[3].to_f]
end
def match_sweaver(formula)
return [] unless (match = formula.match(/(?<operand1>(?:\d+(?:\.\d+)?)|(?:\.\d+))\s*(?<operator>[+\/*-])\s*(?<operand2>(?:\d+(?:\.\d+)?)|(?:\.\d+))/))
return [match[1].to_f, match[2], match[3].to_f]
end
def scan_gaskill(formula)
return [] unless (match = formula.scan(/^\s*(-?\d+(?:\.\d+)?)\s*([+*\/-])\s*(-?\d+(?:\.\d+)?)\s*$/))[0]
return [match[0][0].to_f, match[0][1], match[0][2].to_f]
end
def scan_techbio(formula)
return [] unless (match = formula.scan(/(((\d\.?)+)|[\+\-\*\/])/))
return match.map.with_index {|x,i| i.even? ? x[0].to_f : x[0] }
end
def split_gaskill(formula)
match = formula.split(/(-?\d+(?:\.\d+)?)\s*([+\/*-])\s*(-?\d+(?:\.\d+)?)/)
return [match[1].to_f, match[2], match[3].to_f]
end
def partition_swoveland(formula)
f,op,l = formula.delete(' ').partition(/(?<=\d)[^\d\.]/x)
return [f.to_f, op, l.to_f]
end
def split_swoveland(formula)
f,op,l = formula.split(/([+\/*-])/)
return [f.to_f, op, l.to_f]
end
def split_swoveland2(formula)
f,op,l = formula.split(/\b\s*([+\/*-])\s*/)
return [f.to_f, op, l.to_f]
end
def split_lilue(formula)
return formula.split(%r{(\+|\-|\/|\*)}).map do |x|
unless x =~ /(\+|\-|\/|\*)/ then x.to_f else x end
end
end
def operand_report(result, operands)
"#{(result == operands) ? 'Pass' : ' -- '}"
end
formulae = [
["1+12", [1.0, "+", 12.0]],
["6/0.25", [6.0, "/", 0.25]],
["3/0.125", [3.0, "/", 0.125]],
["30-6", [30.0, "-", 6.0]],
["3*8", [3.0, "*", 8.0]],
["20--4", [20.0, "-", -4.0]],
["33+-9", [33.0, "+", -9.0]],
["-12*-2", [-12.0, "*", -2.0]],
["-72/-3", [-72.0, "/", -3.0]],
["34 - 10", [34.0, "-", 10.0]],
[" 15+ 9", [15.0, "+", 9.0]],
["4*6 ", [4.0, "*", 6.0]],
["b+0.5", []],
["8---0.5", []],
["8+6+10", []],
["15*x", []],
["1.A^ff", []]
]
puts "| Test Case | match | match | scan | scan |partition| split | split | split | split |"
puts "| | Gaskill | sweaver | Gaskill | techbio |Swoveland| Gaskill |Swoveland|Swoveland+| Lilue |"
puts "|------------------------------------------------------------------------------------------------------|"
formulae.each do |pair|
formula = pair[0]
result = pair[1]
func_a = operand_report result, match_gaskill(pair[0])
func_b = operand_report result, match_sweaver(pair[0])
func_c = operand_report result, scan_gaskill(pair[0])
func_d = operand_report result, scan_techbio(pair[0])
func_e = operand_report result, partition_swoveland(pair[0])
func_f = operand_report result, split_gaskill(pair[0])
func_g = operand_report result, split_swoveland(pair[0])
func_h = operand_report result, split_swoveland2(pair[0])
func_i = operand_report result, split_lilue(pair[0])
puts "| #{formula.inspect.ljust(9)} | #{func_a.center(7)} | #{func_b.center(7)} | #{func_c.center(7)} | #{func_d.center(7)} | #{func_e.center(7)} | #{func_f.center(7)} | #{func_g.center(7)} | #{func_h.center(8)} | #{func_h.center(7)} |"
# puts "|------------------------------------------------------------------------------------------------------|"
end
numbers = (0..1000).map {|n| n / 8 }
operators = ["+", "-", "*", "/"]
a = 1_000_000.times.map {|n| "#{numbers.sample}#{operators.sample}#{numbers.sample}" }
puts ""
puts ""
puts RUBY_DESCRIPTION
puts "============================================================"
Benchmark.bm(25) do |x|
x.report("match (Gaskill):") { a.each {|formula| match_gaskill(formula) } }
x.report("match (sweaver2112):") { a.each {|formula| match_sweaver(formula) } }
x.report("scan (Gaskill):") { a.each {|formula| scan_gaskill(formula) } }
x.report("scan (techbio):") { a.each {|formula| scan_techbio(formula) } }
x.report("partition (Swoveland):") { a.each {|formula| partition_swoveland(formula) } }
x.report("split (Gaskill):") { a.each {|formula| split_gaskill(formula) } }
x.report("split (Swoveland):") { a.each {|formula| split_swoveland(formula) } }
x.report("split (Swoveland+):") { a.each {|formula| split_swoveland2(formula) } }
x.report("split (Lilue):") { a.each {|formula| split_lilue(formula) } }
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment