flori-bullshit 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +340 -0
- data/Rakefile +95 -0
- data/VERSION +1 -0
- data/bullshit.gemspec +25 -0
- data/examples/compare.rb +11 -0
- data/examples/fibonacci.rb +75 -0
- data/examples/iteration.rb +116 -0
- data/examples/josephus.rb +136 -0
- data/examples/sorting.rb +363 -0
- data/install.rb +15 -0
- data/lib/bullshit.rb +2244 -0
- data/lib/bullshit/version.rb +8 -0
- data/make_doc.rb +4 -0
- data/tests/test_analysis.rb +321 -0
- data/tests/test_bullshit.rb +222 -0
- data/tests/test_continued_fraction.rb +40 -0
- data/tests/test_distribution.rb +69 -0
- data/tests/test_functions.rb +33 -0
- data/tests/test_newton_bisection.rb +28 -0
- data/tests/test_window.rb +34 -0
- metadata +94 -0
data/examples/compare.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bullshit'
|
4
|
+
require File.join(File.dirname(__FILE__), 'fibonacci')
|
5
|
+
|
6
|
+
FibonacciBenchmark.run # to demonstrate loading
|
7
|
+
|
8
|
+
Bullshit.compare do
|
9
|
+
benchmark FibonacciBenchmark, :fib_iter, :load => yes
|
10
|
+
benchmark FibonacciBenchmark, :fib_memo, :load => yes
|
11
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bullshit'
|
4
|
+
|
5
|
+
class FibonacciBenchmark < Bullshit::RepeatCase
|
6
|
+
warmup yes
|
7
|
+
|
8
|
+
iterations 500
|
9
|
+
|
10
|
+
truncate_data do
|
11
|
+
alpha_level 0.05
|
12
|
+
window_size 10
|
13
|
+
slope_angle 0.003
|
14
|
+
end
|
15
|
+
|
16
|
+
output_dir 'data'
|
17
|
+
data_file yes
|
18
|
+
histogram yes
|
19
|
+
|
20
|
+
autocorrelation do
|
21
|
+
alpha_level 0.05
|
22
|
+
max_lags 50
|
23
|
+
file yes
|
24
|
+
end
|
25
|
+
|
26
|
+
MIN_N = 10_000
|
27
|
+
RANGE_N = 100
|
28
|
+
|
29
|
+
def rand_n
|
30
|
+
MIN_N + rand(RANGE_N + 1)
|
31
|
+
end
|
32
|
+
|
33
|
+
def fib_iter(n)
|
34
|
+
a, b = 0, 1
|
35
|
+
while (n -= 1) >= 0
|
36
|
+
a, b = a + b, a
|
37
|
+
end
|
38
|
+
a
|
39
|
+
end
|
40
|
+
|
41
|
+
def fib_memo(n)
|
42
|
+
@fib_memo ||= Hash.new do |f, i|
|
43
|
+
f[i] = fib_iter(i)
|
44
|
+
end
|
45
|
+
@fib_memo[n]
|
46
|
+
end
|
47
|
+
|
48
|
+
def before_fib_iter
|
49
|
+
@n = rand_n
|
50
|
+
end
|
51
|
+
|
52
|
+
def benchmark_fib_iter
|
53
|
+
@result = fib_iter(@n)
|
54
|
+
end
|
55
|
+
|
56
|
+
def after_fib_iter
|
57
|
+
@result == fib_iter(@n) or raise "wrong result"
|
58
|
+
end
|
59
|
+
|
60
|
+
def before_fib_memo
|
61
|
+
@n = rand_n
|
62
|
+
end
|
63
|
+
|
64
|
+
def benchmark_fib_memo
|
65
|
+
@result = fib_memo(@n)
|
66
|
+
end
|
67
|
+
|
68
|
+
def after_fib_memo
|
69
|
+
@result == fib_iter(@n) or raise "wrong result"
|
70
|
+
end
|
71
|
+
|
72
|
+
def teardown_fib_memo
|
73
|
+
@fib_memo = nil
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bullshit'
|
4
|
+
|
5
|
+
module MyCases
|
6
|
+
def setup
|
7
|
+
@n = 1_000
|
8
|
+
@setup_general = true
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
raise 'setup_general not set' unless @setup_general
|
13
|
+
end
|
14
|
+
|
15
|
+
def setup_for
|
16
|
+
@test_setup = true
|
17
|
+
end
|
18
|
+
|
19
|
+
def benchmark_for
|
20
|
+
a = []
|
21
|
+
for i in 1 .. @n
|
22
|
+
a << i ** 2
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def teardown_for
|
27
|
+
raise "test_setup not set" unless @test_setup
|
28
|
+
end
|
29
|
+
|
30
|
+
def benchmark_times
|
31
|
+
a = []
|
32
|
+
i = 1
|
33
|
+
@n.times do
|
34
|
+
a << i ** 2
|
35
|
+
i += 1
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def benchmark_loop
|
40
|
+
a = []
|
41
|
+
i = 1
|
42
|
+
loop do
|
43
|
+
i < @n or break
|
44
|
+
a << i ** 2
|
45
|
+
i += 1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def benchmark_while
|
50
|
+
a = []
|
51
|
+
i = 1
|
52
|
+
while i < @n
|
53
|
+
a << i ** 2
|
54
|
+
i += 1
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def benchmark_while_fast
|
59
|
+
i = 1
|
60
|
+
while i < @n
|
61
|
+
a = i ** 2
|
62
|
+
i += 1
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def benchmark_inject
|
67
|
+
(1..@n).inject([]) { |a, i| a << i ** 2 }
|
68
|
+
end
|
69
|
+
|
70
|
+
def benchmark_inject2
|
71
|
+
(1..@n).inject([]) { |a, i| a << i ** 2 }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class IterationTimeBenchmark < Bullshit::TimeCase
|
76
|
+
compare_time total
|
77
|
+
warmup yes
|
78
|
+
duration 1
|
79
|
+
batch_size 5
|
80
|
+
|
81
|
+
covering do
|
82
|
+
alpha_level 0.01
|
83
|
+
end
|
84
|
+
|
85
|
+
autocorrelation do
|
86
|
+
file yes
|
87
|
+
end
|
88
|
+
|
89
|
+
output_dir 'data'
|
90
|
+
data_file yes
|
91
|
+
|
92
|
+
histogram yes
|
93
|
+
|
94
|
+
include MyCases
|
95
|
+
end
|
96
|
+
|
97
|
+
class IterationRepeatBenchmark < Bullshit::RepeatCase
|
98
|
+
warmup yes
|
99
|
+
iterations 1000
|
100
|
+
|
101
|
+
covering do
|
102
|
+
alpha_level 0.01
|
103
|
+
end
|
104
|
+
|
105
|
+
autocorrelation yes
|
106
|
+
|
107
|
+
data_file yes
|
108
|
+
output_dir 'data'
|
109
|
+
|
110
|
+
histogram do
|
111
|
+
bins 20
|
112
|
+
file yes
|
113
|
+
end
|
114
|
+
|
115
|
+
include MyCases
|
116
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bullshit'
|
4
|
+
|
5
|
+
module Original
|
6
|
+
class Person
|
7
|
+
attr_reader :count, :prev, :next
|
8
|
+
attr_writer :count, :prev, :next
|
9
|
+
|
10
|
+
def initialize(count)
|
11
|
+
@count = count
|
12
|
+
@prev = nil
|
13
|
+
@next = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def shout(shout, deadif)
|
17
|
+
if shout < deadif
|
18
|
+
return shout + 1
|
19
|
+
end
|
20
|
+
@prev.next = @next
|
21
|
+
@next.prev = @prev
|
22
|
+
return 1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Chain
|
27
|
+
attr_reader :first
|
28
|
+
attr_writer :first
|
29
|
+
|
30
|
+
def initialize(size)
|
31
|
+
@first = nil
|
32
|
+
last = nil
|
33
|
+
for i in (1..size)
|
34
|
+
current = Person.new(i)
|
35
|
+
if @first == nil
|
36
|
+
@first = current
|
37
|
+
end
|
38
|
+
if last != nil
|
39
|
+
last.next = current
|
40
|
+
current.prev = last
|
41
|
+
end
|
42
|
+
last = current
|
43
|
+
end
|
44
|
+
@first.prev = last
|
45
|
+
last.next = @first
|
46
|
+
end
|
47
|
+
|
48
|
+
def kill(nth)
|
49
|
+
current = @first
|
50
|
+
shout = 1
|
51
|
+
while current.next != current
|
52
|
+
shout = current.shout(shout,nth)
|
53
|
+
current = current.next
|
54
|
+
end
|
55
|
+
@first = current
|
56
|
+
return current
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
module Improved
|
62
|
+
class Person
|
63
|
+
attr_accessor :count, :prev, :next
|
64
|
+
|
65
|
+
def initialize(count)
|
66
|
+
@count = count
|
67
|
+
end
|
68
|
+
|
69
|
+
def shout(shout, deadif)
|
70
|
+
if shout < deadif
|
71
|
+
return shout + 1
|
72
|
+
end
|
73
|
+
@prev.next = @next
|
74
|
+
@next.prev = @prev
|
75
|
+
1
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class Chain
|
80
|
+
attr_accessor :first
|
81
|
+
|
82
|
+
def initialize(size)
|
83
|
+
last = nil
|
84
|
+
1.upto(size) do |i|
|
85
|
+
current = Person.new(i)
|
86
|
+
@first ||= current
|
87
|
+
if last
|
88
|
+
last.next = current
|
89
|
+
current.prev = last
|
90
|
+
end
|
91
|
+
last = current
|
92
|
+
end
|
93
|
+
@first.prev = last
|
94
|
+
last.next = @first
|
95
|
+
end
|
96
|
+
|
97
|
+
def kill(nth)
|
98
|
+
current = @first
|
99
|
+
shout = 1
|
100
|
+
while current.next != current
|
101
|
+
shout = current.shout(shout,nth)
|
102
|
+
current = current.next
|
103
|
+
end
|
104
|
+
@first = current
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class JosephusBenchmark < Bullshit::RepeatCase
|
110
|
+
compare_time real
|
111
|
+
warmup aggressive
|
112
|
+
iterations 500
|
113
|
+
|
114
|
+
autocorrelation yes
|
115
|
+
|
116
|
+
N = 1001 # 41
|
117
|
+
|
118
|
+
output_dir 'data'
|
119
|
+
data_file yes
|
120
|
+
|
121
|
+
output_filename "#{benchmark_name}.log"
|
122
|
+
|
123
|
+
histogram do
|
124
|
+
bins 20
|
125
|
+
end
|
126
|
+
|
127
|
+
def benchmark_josephus_original
|
128
|
+
chain = Original::Chain.new(N)
|
129
|
+
chain.kill(3)
|
130
|
+
end
|
131
|
+
|
132
|
+
def benchmark_josephus_improved
|
133
|
+
chain = Improved::Chain.new(N)
|
134
|
+
chain.kill(3)
|
135
|
+
end
|
136
|
+
end
|
data/examples/sorting.rb
ADDED
@@ -0,0 +1,363 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bullshit'
|
4
|
+
|
5
|
+
class SortingBenchmark < Bullshit::RangeCase
|
6
|
+
compare_time real
|
7
|
+
warmup yes
|
8
|
+
range 1..200
|
9
|
+
scatter 3
|
10
|
+
|
11
|
+
data_file yes
|
12
|
+
output_dir 'data'
|
13
|
+
|
14
|
+
def prepare_random_array
|
15
|
+
@ary = Array.new(args) { rand(args * 10) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def prepare_sorted_array
|
19
|
+
@ary = Array.new(args) { rand(args * 10) }
|
20
|
+
@ary.sort!
|
21
|
+
end
|
22
|
+
|
23
|
+
def check_result
|
24
|
+
@result == @ary.sort or raise "sorting failure"
|
25
|
+
end
|
26
|
+
|
27
|
+
# Ruby internal sort (an optimized quicksort implementation)
|
28
|
+
|
29
|
+
# random array
|
30
|
+
alias before_ruby_sort prepare_random_array
|
31
|
+
|
32
|
+
def benchmark_ruby_sort
|
33
|
+
@result = @ary.sort
|
34
|
+
end
|
35
|
+
|
36
|
+
alias after_ruby_sort check_result
|
37
|
+
|
38
|
+
# sorted array
|
39
|
+
alias before_ruby_sort_sorted prepare_sorted_array
|
40
|
+
|
41
|
+
alias benchmark_ruby_sort_sorted benchmark_ruby_sort
|
42
|
+
|
43
|
+
alias after_ruby_sort_sorted check_result
|
44
|
+
|
45
|
+
# Quicksort in Ruby
|
46
|
+
|
47
|
+
def quicksort(a)
|
48
|
+
return [] if a.empty?
|
49
|
+
left, right = a[1..-1].partition { |y| y <= a.first }
|
50
|
+
quicksort(left) + [ a.first ] + quicksort(right)
|
51
|
+
end
|
52
|
+
|
53
|
+
# random array
|
54
|
+
alias before_quicksort prepare_random_array
|
55
|
+
|
56
|
+
def benchmark_quicksort
|
57
|
+
@result = quicksort @ary
|
58
|
+
end
|
59
|
+
|
60
|
+
alias after_quicksort check_result
|
61
|
+
|
62
|
+
# sorted array
|
63
|
+
alias before_quicksort_sorted prepare_sorted_array
|
64
|
+
|
65
|
+
alias benchmark_quicksort_sorted benchmark_quicksort
|
66
|
+
|
67
|
+
alias after_quicksort_sorted check_result
|
68
|
+
|
69
|
+
# Quicksort in Ruby with median pivot
|
70
|
+
|
71
|
+
def find_median_index(orig_a)
|
72
|
+
a = orig_a.dup
|
73
|
+
k = a.size / 2
|
74
|
+
l = 0
|
75
|
+
m = a.size - 1
|
76
|
+
while l < m
|
77
|
+
x = a[k]
|
78
|
+
i = l
|
79
|
+
j = m
|
80
|
+
begin
|
81
|
+
i += 1 while a[i] < x
|
82
|
+
j -= 1 while x < a[j]
|
83
|
+
if i <= j
|
84
|
+
a[i], a[j] = a[j], a[i]
|
85
|
+
i += 1
|
86
|
+
j -= 1
|
87
|
+
end
|
88
|
+
end while i <= j
|
89
|
+
l = i if j < k
|
90
|
+
m = j if k < i
|
91
|
+
end
|
92
|
+
orig_a.index(a[k])
|
93
|
+
end
|
94
|
+
|
95
|
+
def median_quicksort(a)
|
96
|
+
return [] if a.empty?
|
97
|
+
i = find_median_index a
|
98
|
+
a[0], a[i] = a[i], a[0]
|
99
|
+
left, right = a[1..-1].partition { |y| y <= a.first }
|
100
|
+
median_quicksort(left) + [ a.first ] + median_quicksort(right)
|
101
|
+
end
|
102
|
+
|
103
|
+
# random array
|
104
|
+
alias before_median_quicksort prepare_random_array
|
105
|
+
|
106
|
+
def benchmark_median_quicksort
|
107
|
+
@result = median_quicksort @ary
|
108
|
+
end
|
109
|
+
|
110
|
+
alias after_median_quicksort check_result
|
111
|
+
|
112
|
+
# sorted array
|
113
|
+
alias before_median_quicksort_sorted prepare_sorted_array
|
114
|
+
|
115
|
+
alias benchmark_median_quicksort_sorted benchmark_median_quicksort
|
116
|
+
|
117
|
+
alias after_median_quicksort_sorted check_result
|
118
|
+
|
119
|
+
# Insertionsort-Quicksort-Hybrid in Ruby
|
120
|
+
|
121
|
+
def quicksort_hybrid(a)
|
122
|
+
if a.size < 7
|
123
|
+
insertionsort(a)
|
124
|
+
else
|
125
|
+
i = find_median_index a
|
126
|
+
a[0], a[i] = a[i], a[0]
|
127
|
+
left, right = a[1..-1].partition { |y| y <= a.first }
|
128
|
+
quicksort_hybrid(left) + [ a.first ] + quicksort_hybrid(right)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# random array
|
133
|
+
alias before_quicksort_hybrid prepare_random_array
|
134
|
+
|
135
|
+
def benchmark_quicksort_hybrid
|
136
|
+
@result = quicksort_hybrid @ary
|
137
|
+
end
|
138
|
+
|
139
|
+
alias after_quicksort_hybrid check_result
|
140
|
+
|
141
|
+
# sorted array
|
142
|
+
alias before_quicksort_hybrid_sorted prepare_sorted_array
|
143
|
+
|
144
|
+
alias benchmark_quicksort_hybrid_sorted benchmark_quicksort_hybrid
|
145
|
+
|
146
|
+
alias after_quicksort_hybrid_sorted check_result
|
147
|
+
|
148
|
+
# Selectionsort in Ruby
|
149
|
+
|
150
|
+
def selectionsort(a)
|
151
|
+
a = a.dup
|
152
|
+
for start in 0...(a.size - 1)
|
153
|
+
min = start
|
154
|
+
for i in (start + 1)...a.size
|
155
|
+
a[i] < a[min] and min = i
|
156
|
+
end
|
157
|
+
a[start], a[min] = a[min], a[start]
|
158
|
+
end
|
159
|
+
a
|
160
|
+
end
|
161
|
+
|
162
|
+
# random array
|
163
|
+
alias before_selectionsort prepare_random_array
|
164
|
+
|
165
|
+
def benchmark_selectionsort
|
166
|
+
@result = selectionsort @ary
|
167
|
+
end
|
168
|
+
|
169
|
+
alias after_selectionsort check_result
|
170
|
+
|
171
|
+
# sorted array
|
172
|
+
alias before_selectionsort_sorted prepare_sorted_array
|
173
|
+
|
174
|
+
alias benchmark_selectionsort_sorted benchmark_selectionsort
|
175
|
+
|
176
|
+
alias after_selectionsort_sorted check_result
|
177
|
+
|
178
|
+
# Insertionsort in Ruby
|
179
|
+
|
180
|
+
def insertionsort(a)
|
181
|
+
a = a.dup
|
182
|
+
for i in 1...a.size
|
183
|
+
j, x = i - 1, a[i]
|
184
|
+
while j >= 0 and a[j] > x
|
185
|
+
a[j + 1] = a[j]
|
186
|
+
j -= 1
|
187
|
+
end
|
188
|
+
a[j + 1] = x
|
189
|
+
end
|
190
|
+
a
|
191
|
+
end
|
192
|
+
|
193
|
+
# random array
|
194
|
+
alias before_insertionsort prepare_random_array
|
195
|
+
|
196
|
+
def benchmark_insertionsort
|
197
|
+
@result = insertionsort @ary
|
198
|
+
end
|
199
|
+
|
200
|
+
alias after_insertionsort check_result
|
201
|
+
|
202
|
+
# sorted array
|
203
|
+
alias before_insertionsort_sorted prepare_sorted_array
|
204
|
+
|
205
|
+
alias benchmark_insertionsort_sorted benchmark_insertionsort
|
206
|
+
|
207
|
+
alias after_insertionsort_sorted check_result
|
208
|
+
|
209
|
+
# Shellsort in Ruby
|
210
|
+
|
211
|
+
def shellsort(a)
|
212
|
+
a = a.dup
|
213
|
+
s = a.size / 2
|
214
|
+
while s > 0
|
215
|
+
for i in 0...a.size
|
216
|
+
j, t = i, a[i]
|
217
|
+
while j >= s and a[j - s] > t
|
218
|
+
a[j] = a[j - s]
|
219
|
+
j -= s
|
220
|
+
end
|
221
|
+
a[j] = t
|
222
|
+
end
|
223
|
+
s = s == 1 ? 0 : s / 2
|
224
|
+
end
|
225
|
+
a
|
226
|
+
end
|
227
|
+
|
228
|
+
# random array
|
229
|
+
alias before_shellsort prepare_random_array
|
230
|
+
|
231
|
+
def benchmark_shellsort
|
232
|
+
@result = shellsort @ary
|
233
|
+
end
|
234
|
+
|
235
|
+
alias after_shellsort check_result
|
236
|
+
|
237
|
+
# sorted array
|
238
|
+
alias before_shellsort_sorted prepare_sorted_array
|
239
|
+
|
240
|
+
alias benchmark_shellsort_sorted benchmark_shellsort
|
241
|
+
|
242
|
+
alias after_shellsort_sorted check_result
|
243
|
+
|
244
|
+
# Bubblesort in Ruby
|
245
|
+
|
246
|
+
def bubblesort(a)
|
247
|
+
a = a.dup
|
248
|
+
for j in 0...a.size
|
249
|
+
for i in 1...(a.size - j)
|
250
|
+
a[i], a[i - 1] = a[i - 1], a[i] if a[i] < a[i - 1]
|
251
|
+
end
|
252
|
+
end
|
253
|
+
a
|
254
|
+
end
|
255
|
+
|
256
|
+
# random array
|
257
|
+
alias before_bubblesort prepare_random_array
|
258
|
+
|
259
|
+
def benchmark_bubblesort
|
260
|
+
@result = bubblesort @ary
|
261
|
+
end
|
262
|
+
|
263
|
+
alias after_bubblesort check_result
|
264
|
+
|
265
|
+
# sorted array
|
266
|
+
alias before_bubblesort_sorted prepare_sorted_array
|
267
|
+
|
268
|
+
alias benchmark_bubblesort_sorted benchmark_bubblesort
|
269
|
+
|
270
|
+
alias after_bubblesort_sorted check_result
|
271
|
+
|
272
|
+
# Mergesort in Ruby
|
273
|
+
|
274
|
+
def merge(a, b)
|
275
|
+
case
|
276
|
+
when a.empty? then b
|
277
|
+
when b.empty? then a
|
278
|
+
when a.first < b.first then a[0, 1].concat merge(a[1..-1], b)
|
279
|
+
else b[0, 1].concat merge(a, b[1..-1])
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def mergesort(a)
|
284
|
+
if a.size <= 1
|
285
|
+
a
|
286
|
+
else
|
287
|
+
mid = a.size / 2
|
288
|
+
merge( mergesort(a[0, mid]), mergesort(a[mid..-1]) )
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
# random array
|
293
|
+
alias before_mergesort prepare_random_array
|
294
|
+
|
295
|
+
def benchmark_mergesort
|
296
|
+
@result = mergesort @ary
|
297
|
+
end
|
298
|
+
|
299
|
+
alias after_mergesort check_result
|
300
|
+
|
301
|
+
# sorted array
|
302
|
+
alias before_mergesort_sorted prepare_sorted_array
|
303
|
+
|
304
|
+
alias benchmark_mergesort_sorted benchmark_mergesort
|
305
|
+
|
306
|
+
alias after_mergesort_sorted check_result
|
307
|
+
|
308
|
+
# Heapsort in Ruby
|
309
|
+
def sift_down(a, start, ende)
|
310
|
+
root = start
|
311
|
+
while root * 2 + 1 <= ende
|
312
|
+
child = root * 2 + 1
|
313
|
+
if child + 1 <= ende and a[child] < a[child + 1]
|
314
|
+
child += 1
|
315
|
+
end
|
316
|
+
if a[root] < a[child]
|
317
|
+
a[root], a[child] = a[child], a[root]
|
318
|
+
root = child
|
319
|
+
else
|
320
|
+
return
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
def heapify(a)
|
326
|
+
count = a.size
|
327
|
+
|
328
|
+
start = (count - 2) / 2
|
329
|
+
while start >= 0
|
330
|
+
sift_down(a, start, count - 1)
|
331
|
+
start -= 1
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
def heapsort(a)
|
336
|
+
a = a.dup
|
337
|
+
heapify(a)
|
338
|
+
|
339
|
+
ende = a.size - 1
|
340
|
+
while ende > 0
|
341
|
+
a[ende], a[0] = a[0], a[ende]
|
342
|
+
ende -= 1
|
343
|
+
sift_down(a, 0, ende)
|
344
|
+
end
|
345
|
+
a
|
346
|
+
end
|
347
|
+
|
348
|
+
# random array
|
349
|
+
alias before_heapsort prepare_random_array
|
350
|
+
|
351
|
+
def benchmark_heapsort
|
352
|
+
@result = heapsort @ary
|
353
|
+
end
|
354
|
+
|
355
|
+
alias after_heapsort check_result
|
356
|
+
|
357
|
+
# sorted array
|
358
|
+
alias before_heapsort_sorted prepare_sorted_array
|
359
|
+
|
360
|
+
alias benchmark_heapsort_sorted benchmark_heapsort
|
361
|
+
|
362
|
+
alias after_heapsort_sorted check_result
|
363
|
+
end
|