-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathfibonacci.rb
67 lines (54 loc) · 1.84 KB
/
fibonacci.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# MRI hack to enable tail-call optimization making the recursive version not blow the stack:
# I'm using ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0]
RubyVM::InstructionSequence.compile_option = {
tailcall_optimization: true,
trace_instruction: false
}
class Fib
def run_enumerative(n)
# with hash memoization... real slow tho
# n.times.reduce([0,1]){|memo, num| memo + [memo[-2] + memo[-1]]}
# with a lambda
(0..n).inject([1,0]) { |(a,b), _| [b, a+b] }[0]
end
def run_procedural(n)
curr, nxt = 0, 1
n.times {
curr, nxt = nxt, curr + nxt
}
curr
end
def run_recursive(n)
_run_recursive(n, 0, 1)
end
# this hack does work, but as you can see, looks so hacky
# If you do not use this, the stack will blow for any arg of any significant size.
# Doesn't mean it will run fast, though...
# Taken from http://nithinbekal.com/posts/ruby-tco/
RubyVM::InstructionSequence.new(<<-EOS).eval
def _run_recursive(n, res, nxt)
return res unless n > 0
_run_recursive(n-1, nxt, res+nxt)
end
EOS
end
times = 1000000
# I commented the recursive version out because, even though it doesn't blow the stack,
# it took waaaay too long for an input of 500000
# begin
# t = Time.now
# Fib.new.run_recursive times
# recursive_total_time = Time.now - t
# rescue SystemStackError => e
# puts "Ruby recursive solution blows up with fib(#{times})."
# puts e.inspect
# end
t = Time.now
Fib.new.run_procedural times
procedural_total_time = Time.now - t
t = Time.now
Fib.new.run_enumerative times
enumerative_total_time = Time.now - t
# puts "Running Ruby recursive fib(#{times}) takes #{recursive_total_time} seconds"
puts "Running Ruby procedural fib(#{times}) takes #{procedural_total_time} seconds"
puts "Running Ruby enumerative fib(#{times}) takes #{enumerative_total_time} seconds"