Skip to content

Instantly share code, notes, and snippets.

@intrip
Created March 17, 2017 12:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save intrip/03d0093c9602cf7df3344b6bdf281cd4 to your computer and use it in GitHub Desktop.
Save intrip/03d0093c9602cf7df3344b6bdf281cd4 to your computer and use it in GitHub Desktop.
# Base factorial version not tail recursive
def fact(n)
return 1 if n <= 1
n * fact(n-1)
end
# enable tail recursive optimization
RubyVM::InstructionSequence.compile_option = {
tailcall_optimization: true,
trace_instruction: false
}
# Tail recursive version
RubyVM::InstructionSequence.compile(<<-EOF).eval
def fact_tail(n, acc=1)
return acc if n <= 1
fact_tail(n-1, n*acc)
end
EOF
# saves the params in a stack array
# actually is faster then the tail_recursive version
def fact_stack(val)
res = 1
params = [val]
while !params.empty?
current_param = params.delete_at(0)
return res if current_param <= 1
if current_param > 1
res = current_param * res
params << (current_param -1)
end
end
end
# this will print out "stack level too deep."
# fact(100000)
# now this won't stack overflow
#fact_tail(100000)
# this won't stack overflow either
#fact_stack(100000)
times = 200000
require 'benchmark'
Benchmark.bm do |x|
# x.report("fact: ") {fact(times) }
x.report("fact_tail: ") { fact_tail(times)}
x.report("fact_stack: ") { fact_stack(times)}
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment