rubylabs 0.5.4
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/LICENSE +20 -0
- data/README.rdoc +9 -0
- data/Rakefile +63 -0
- data/VERSION +1 -0
- data/bin/bb.rb +12 -0
- data/bin/statistics2-0.53/ext/extconf.rb +11 -0
- data/bin/statistics2-0.53/ext/show.rb +11 -0
- data/bin/statistics2-0.53/ext/t.rb +46 -0
- data/bin/statistics2-0.53/mklist.rb +26 -0
- data/bin/statistics2-0.53/sample-tbl.rb +129 -0
- data/bin/statistics2-0.53/statistics2.rb +532 -0
- data/bin/statistics2-0.53/t-inv.rb +54 -0
- data/bin/statistics2.rb +532 -0
- data/data/aafreq.txt +20 -0
- data/data/cars.txt +50 -0
- data/data/century.txt +1 -0
- data/data/colors.txt +64 -0
- data/data/earth.yaml +15 -0
- data/data/fruit.txt +45 -0
- data/data/hacodes.txt +35 -0
- data/data/hafreq.txt +16 -0
- data/data/hvfreq.txt +5 -0
- data/data/nbody.R +23 -0
- data/data/nbody.out +731 -0
- data/data/nbody.pdf +3111 -0
- data/data/nbody.png +0 -0
- data/data/nbody3d.pdf +3201 -0
- data/data/outer.pdf +182785 -0
- data/data/solar.dat +36501 -0
- data/data/solarsystem.txt +17 -0
- data/data/suits.txt +1 -0
- data/data/wordlist.txt +210653 -0
- data/lib/bitlab.rb +624 -0
- data/lib/elizalab.rb +523 -0
- data/lib/encryptionlab.rb +42 -0
- data/lib/hashlab.rb +224 -0
- data/lib/introlab.rb +14 -0
- data/lib/iterationlab.rb +130 -0
- data/lib/randomlab.rb +294 -0
- data/lib/recursionlab.rb +228 -0
- data/lib/rubylabs.rb +507 -0
- data/lib/sievelab.rb +58 -0
- data/lib/sortlab.rb +213 -0
- data/lib/spherelab.rb +352 -0
- data/lib/temps.rb +41 -0
- data/lib/tsplab.rb +416 -0
- data/lib/viewer.rb +65 -0
- data/test/bit_test.rb +175 -0
- data/test/encryption_test.rb +20 -0
- data/test/iteration_test.rb +40 -0
- data/test/random_test.rb +64 -0
- data/test/recursion_test.rb +47 -0
- data/test/rubylabs_test.rb +18 -0
- data/test/sieve_test.rb +28 -0
- data/test/sphere_test.rb +130 -0
- data/test/temps_test.rb +24 -0
- data/test/test_helper.rb +18 -0
- metadata +112 -0
data/lib/recursionlab.rb
ADDED
@@ -0,0 +1,228 @@
|
|
1
|
+
|
2
|
+
=begin rdoc
|
3
|
+
|
4
|
+
== RecursionLab
|
5
|
+
|
6
|
+
Divide and conquer algorithms for searching and sorting.
|
7
|
+
The methods implemented in this module are +bsearch+ (binary search),
|
8
|
+
+msort+ (merge sort), and +qsort!+ (QuickSort). The module also
|
9
|
+
contains 'helper methods' that can be used to trace the execution
|
10
|
+
of the algorithms.
|
11
|
+
|
12
|
+
=end
|
13
|
+
|
14
|
+
module RubyLabs
|
15
|
+
|
16
|
+
module RecursionLab
|
17
|
+
|
18
|
+
=begin rdoc
|
19
|
+
|
20
|
+
Linear search -- use for baseline tests. Form that makes it easy to attach
|
21
|
+
probe to count comparisons.
|
22
|
+
=end
|
23
|
+
|
24
|
+
# :begin :search
|
25
|
+
def search(a, k)
|
26
|
+
i = 0
|
27
|
+
while i < a.length
|
28
|
+
return i if a[i] == k
|
29
|
+
i += 1
|
30
|
+
end
|
31
|
+
return nil
|
32
|
+
end
|
33
|
+
# :end :search
|
34
|
+
|
35
|
+
|
36
|
+
=begin rdoc
|
37
|
+
|
38
|
+
Call <tt>bsearch(k, a)</tt> to search for item +k+ in array +a+, using
|
39
|
+
the binary search algorithm. Based on the specification in Introduction
|
40
|
+
to Algorithms, by Cormen et al.
|
41
|
+
|
42
|
+
=end
|
43
|
+
|
44
|
+
# :begin :bsearch
|
45
|
+
def bsearch(a, k)
|
46
|
+
lower = -1
|
47
|
+
upper = a.length
|
48
|
+
while true # iteration ends with return statement
|
49
|
+
mid = (lower + upper) / 2 # set the mid point for this iteration
|
50
|
+
return nil if upper == lower + 1 # search fails if the region is empty
|
51
|
+
return mid if k == a[mid] # search succeeds if k is at the midpoint
|
52
|
+
if k < a[mid]
|
53
|
+
upper = mid # next search: lower half of the region
|
54
|
+
else
|
55
|
+
lower = mid # next search: upper half
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
# :end :bsearch
|
60
|
+
|
61
|
+
=begin rdoc
|
62
|
+
|
63
|
+
Recursive implementation of binary search.
|
64
|
+
|
65
|
+
=end
|
66
|
+
|
67
|
+
# :begin :rsearch
|
68
|
+
def rsearch(a, k, lower = -1, upper = a.length)
|
69
|
+
mid = (lower + upper) / 2
|
70
|
+
return nil if upper == lower + 1 # search fails if the region is empty
|
71
|
+
return mid if k == a[mid] # search succeeds if k is at the midpoint
|
72
|
+
if k < a[mid]
|
73
|
+
return rsearch(a, k, lower, mid)
|
74
|
+
else
|
75
|
+
return rsearch(a, k, mid, upper)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
# :end :rsearch
|
79
|
+
|
80
|
+
=begin rdoc
|
81
|
+
A helper method that can be called from a probe to display the contents
|
82
|
+
of an array during a search or sort.
|
83
|
+
=end
|
84
|
+
|
85
|
+
def brackets(a, left, right = a.length-1, mid = nil) # :nodoc:
|
86
|
+
left = 0 if left < 0
|
87
|
+
right = a.length-1 if right >= a.length
|
88
|
+
pre = left == 0 ? "" : " " + a.slice(0..(left-1)).join(" ") + " "
|
89
|
+
inner = left <= right ? a.slice(left..right).join(" ") : ""
|
90
|
+
post = " " + a.slice(right+1..-1).join(" ")
|
91
|
+
res = pre + "[" + inner + "]" + post
|
92
|
+
if mid && left < right
|
93
|
+
res[res.index(a[mid].to_s)-1] = ?*
|
94
|
+
end
|
95
|
+
return res
|
96
|
+
end
|
97
|
+
|
98
|
+
=begin rdoc
|
99
|
+
|
100
|
+
A test harness for bsearch -- makes an array, gets an item not in the array,
|
101
|
+
counts comparisons (assuming user has set a counting probe)
|
102
|
+
|
103
|
+
=end
|
104
|
+
|
105
|
+
def bsearch_count(n)
|
106
|
+
a = TestArray.new(n)
|
107
|
+
x = a.random(:fail)
|
108
|
+
count { bsearch(a,x) }
|
109
|
+
end
|
110
|
+
|
111
|
+
=begin rdoc
|
112
|
+
|
113
|
+
Merge sort. Makes a copy of the input array, returns a sorted
|
114
|
+
version of the copy. Uses a "helper function" to
|
115
|
+
combine successively bigger pieces of the input array.
|
116
|
+
|
117
|
+
=end
|
118
|
+
|
119
|
+
# :begin :msort :merge :less
|
120
|
+
def msort(a)
|
121
|
+
g = 1 # group size
|
122
|
+
while g < a.length
|
123
|
+
tmp = [] # append merged groups to this array
|
124
|
+
i = 0 # first group starts here
|
125
|
+
while i < a.length
|
126
|
+
tmp += merge(a, i, g) # merge groups at a[i] and a[i+g], append to tmp
|
127
|
+
i += 2*g # next groups starts 2*g places to the right of i
|
128
|
+
end
|
129
|
+
g *= 2 # double the group size
|
130
|
+
a = tmp # a now refers to array just built
|
131
|
+
end
|
132
|
+
return a
|
133
|
+
end
|
134
|
+
# :end :msort
|
135
|
+
|
136
|
+
# "Helper function" to merge two blocks. A call of the form merge(a, i, n) creates
|
137
|
+
# a new list by merging n-element lists at a[i] and a[i+n].
|
138
|
+
|
139
|
+
# :begin :merge
|
140
|
+
def merge(a, i, n) # :nodoc:
|
141
|
+
ix = j = min(i + n, a.length)
|
142
|
+
jx = min(j + n, a.length)
|
143
|
+
res = []
|
144
|
+
while i < ix || j < jx
|
145
|
+
if j == jx || i < ix && less( a[i], a[j] )
|
146
|
+
res << a[i]
|
147
|
+
i += 1
|
148
|
+
else
|
149
|
+
res << a[j]
|
150
|
+
j += 1
|
151
|
+
end
|
152
|
+
end
|
153
|
+
return res
|
154
|
+
end
|
155
|
+
# :end :merge
|
156
|
+
|
157
|
+
# :begin :less
|
158
|
+
def less(x, y)
|
159
|
+
return x < y
|
160
|
+
end
|
161
|
+
# :end :less
|
162
|
+
|
163
|
+
# Helper function to print brackets during merge sort
|
164
|
+
|
165
|
+
def msort_brackets(a, n) # :nodoc:
|
166
|
+
# return " [" + a[i..i+2*n-1].join(" ") + "] "
|
167
|
+
res = []
|
168
|
+
i = 0
|
169
|
+
while i < a.length
|
170
|
+
res << a[i..((i+n)-1)].join(" ")
|
171
|
+
i += n
|
172
|
+
end
|
173
|
+
return "[" + res.join("] [") + "]"
|
174
|
+
end
|
175
|
+
|
176
|
+
=begin rdoc
|
177
|
+
|
178
|
+
QuickSort, based on the description from Cormen et al. Sorts the input array in place.
|
179
|
+
The parameters (using notation from Cormen et al): +p+ is the left boundary of the region
|
180
|
+
to sort, and +r+ is right boundary. The call to +partition+ sets +q+, the new boundary
|
181
|
+
between two sub-regions.
|
182
|
+
|
183
|
+
=end
|
184
|
+
|
185
|
+
# :begin :qsort :partition
|
186
|
+
def qsort(a, p = 0, r = a.length-1) # sort the region bounded by p and r
|
187
|
+
a = a.dup if p == 0 && r == a.length-1 # don't modify the input array (top level only)
|
188
|
+
if p < r
|
189
|
+
q = partition(a, p, r) # q is boundary between small items and large items
|
190
|
+
qsort(a, p, q) # sort small items (range from p to q)
|
191
|
+
qsort(a, q+1, r) # sort large items (range from q+1 to r)
|
192
|
+
end
|
193
|
+
return a
|
194
|
+
end
|
195
|
+
# :end :qsort
|
196
|
+
|
197
|
+
# :begin :partition
|
198
|
+
def partition(a, p, r) # partition the region bounded by p and r
|
199
|
+
x = a[p] # x is the pivot value
|
200
|
+
i = p - 1
|
201
|
+
j = r + 1
|
202
|
+
while true # squeeze i, j until they point at items to exchange
|
203
|
+
loop { j = j - 1; break if a[j] <= x }
|
204
|
+
loop { i = i + 1; break if a[i] >= x }
|
205
|
+
if i < j
|
206
|
+
a[i], a[j] = a[j], a[i] # exchange items at locations i and j
|
207
|
+
else
|
208
|
+
return j # no more exchanges; return location that separates regions
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
# :end :partition
|
213
|
+
|
214
|
+
# Helper procedure used to trace the execution of qsort
|
215
|
+
|
216
|
+
def qsort_brackets(a, left, right) # :nodoc:
|
217
|
+
tmp = []
|
218
|
+
tmp += a[ 0 .. (left-1) ] if left > 0
|
219
|
+
tmp << "["
|
220
|
+
tmp += a[ left .. right ] if right >= 0
|
221
|
+
tmp << "]"
|
222
|
+
tmp += a[ (right+1) .. (a.length-1) ] if right < a.length
|
223
|
+
return tmp.join(" ")
|
224
|
+
end
|
225
|
+
|
226
|
+
end # RecursionLab
|
227
|
+
|
228
|
+
end # RubyLabs
|