flori-bullshit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|