rubylabs 0.6.4 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/randomlab.rb +143 -224
- data/lib/rubylabs.rb +262 -38
- data/lib/spherelab.rb +566 -209
- data/lib/tsplab.rb +308 -276
- data/test/sphere_test.rb +32 -0
- metadata +2 -22
- data/data/aafreq.txt +0 -20
- data/data/cars.txt +0 -50
- data/data/century.txt +0 -1
- data/data/colors.txt +0 -64
- data/data/earth.yaml +0 -15
- data/data/fruit.txt +0 -45
- data/data/hacodes.txt +0 -35
- data/data/hafreq.txt +0 -16
- data/data/hvfreq.txt +0 -5
- data/data/nbody.R +0 -23
- data/data/nbody.out +0 -731
- data/data/nbody.pdf +0 -3111
- data/data/nbody.png +0 -0
- data/data/nbody3d.pdf +0 -3201
- data/data/outer.pdf +0 -182785
- data/data/solarsystem.txt +0 -17
- data/data/suits.txt +0 -1
- data/data/wordlist.txt +0 -210653
- data/lib/sortlab.rb +0 -213
- data/lib/viewer.rb +0 -65
data/lib/sortlab.rb
DELETED
@@ -1,213 +0,0 @@
|
|
1
|
-
|
2
|
-
=begin rdoc
|
3
|
-
|
4
|
-
== SortLab
|
5
|
-
|
6
|
-
Instrumented versions of the sorting algorithms described in the chapters
|
7
|
-
on iterative algorithms and recursive algorithms. The versions here are
|
8
|
-
not intended to be viewed by students -- those implementations are in the
|
9
|
-
modules named IterationLab and RecursionLab.
|
10
|
-
|
11
|
-
The three public methods implemented here are +isort+ (insertion sort),
|
12
|
-
+msort+ (mergesort), and +qsort+ (quicksort). The only required parameter
|
13
|
-
is an array to sort. A method will make a copy of the parameter and return
|
14
|
-
a sorted version of the copy.
|
15
|
-
|
16
|
-
An optional second parameter can be used when running experiments:
|
17
|
-
:trace print the state of the array after each iteration of the outer loop
|
18
|
-
:count return a count of the number of comparisons made instead of the sorted array
|
19
|
-
:timer return the execution time in seconds instead of the sorted array
|
20
|
-
|
21
|
-
=end
|
22
|
-
|
23
|
-
module RubyLabs
|
24
|
-
|
25
|
-
module SortLab
|
26
|
-
|
27
|
-
=begin rdoc
|
28
|
-
|
29
|
-
The Timer class implements a simpler timer. Call +Timer.start+ to start
|
30
|
-
the timer, and +Timer.stop+ to get the elapsed time since the call to
|
31
|
-
+Timer.start+.
|
32
|
-
=end
|
33
|
-
|
34
|
-
class Timer
|
35
|
-
|
36
|
-
def Timer.start
|
37
|
-
@@tstart = Time.now
|
38
|
-
end
|
39
|
-
|
40
|
-
def Timer.stop
|
41
|
-
return Time.now - @@tstart
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
=begin rdoc
|
47
|
-
Insertion sort.
|
48
|
-
=end
|
49
|
-
|
50
|
-
def isort(a, mode = nil)
|
51
|
-
a = a.clone
|
52
|
-
Timer.start if mode == :timer
|
53
|
-
count = 0
|
54
|
-
for i in 1..a.length - 1
|
55
|
-
puts isort_brackets(a,i) if mode == :trace
|
56
|
-
x = a.slice!(i)
|
57
|
-
j = i - 1
|
58
|
-
while j >= 0 && (count += 1) > 0 && a[j] > x
|
59
|
-
j = j - 1
|
60
|
-
end
|
61
|
-
a.insert(j + 1, x)
|
62
|
-
end
|
63
|
-
return case mode
|
64
|
-
when :count : count
|
65
|
-
when :timer : Timer.stop
|
66
|
-
else a
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
=begin rdoc
|
71
|
-
Helper method for printing the state of the array during insertion sort.
|
72
|
-
=end
|
73
|
-
|
74
|
-
def isort_brackets(a, i)
|
75
|
-
pre = (i == 0) ? [] : a.slice(0..(i-1))
|
76
|
-
post = (i <= a.length) ? a.slice(i..-1) : []
|
77
|
-
return "[" + pre.join(", ") + "] [" + post.join(", ") + "]"
|
78
|
-
end
|
79
|
-
|
80
|
-
|
81
|
-
# Merge sort. Makes a copy of the input Array, returns a sorted
|
82
|
-
# version of the copy. Uses a "helper function" named merge to
|
83
|
-
# combine successively bigger pieces of the input array.
|
84
|
-
|
85
|
-
def msort(a, mode = nil)
|
86
|
-
a = a.clone # don't modify the input array!
|
87
|
-
Timer.start
|
88
|
-
n = 1 # size of "pile" at each step
|
89
|
-
count = 0
|
90
|
-
while n < a.length
|
91
|
-
i = 0 # first pile starts here
|
92
|
-
while i < a.length
|
93
|
-
count += merge(a,i,n) # merge piles at a[i] and i+n, put at a[i]
|
94
|
-
print " [" + a[i..i+2*n-1].join(" ") + "] " if mode == :trace
|
95
|
-
i += 2*n # next pile starts at i+2n
|
96
|
-
end
|
97
|
-
puts if mode == :trace
|
98
|
-
n *= 2 # double the pile size
|
99
|
-
end
|
100
|
-
if mode == :timer
|
101
|
-
return Timer.stop
|
102
|
-
elsif mode == :count
|
103
|
-
return count
|
104
|
-
else
|
105
|
-
return a
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
# "Helper function" to merge two "piles" in place. A call to this method
|
110
|
-
# merges n-element lists at a[i] and a[i+n] and stores the merged result
|
111
|
-
# in the array starting at a[i]. Uses an auxiliary list to hold items moved
|
112
|
-
# from a[i..i+n-1], then merges those into place at a[i+n].
|
113
|
-
|
114
|
-
def merge(a, i, n)
|
115
|
-
aux = []
|
116
|
-
j = k = i + n
|
117
|
-
kmax = i + 2*n
|
118
|
-
kmax = a.length if kmax > a.length
|
119
|
-
count = 0
|
120
|
-
# phase 1 -- copy items from a[i..i+n-1] to aux
|
121
|
-
while i < k
|
122
|
-
if a[j] && a[j] < a[i] && (aux.empty? || a[j] < aux[0])
|
123
|
-
aux << a[i]
|
124
|
-
a[i] = a[j]
|
125
|
-
j += 1
|
126
|
-
count += 1
|
127
|
-
elsif !aux.empty? && aux[0] < a[i]
|
128
|
-
aux << a[i]
|
129
|
-
a[i] = aux.shift
|
130
|
-
count += 1
|
131
|
-
end
|
132
|
-
i += 1
|
133
|
-
end
|
134
|
-
# phase 2 -- merge aux into empty slots in a[i+n..i+2n]
|
135
|
-
while k < kmax && ! aux.empty?
|
136
|
-
if j == kmax || a[j] > aux[0]
|
137
|
-
a[k] = aux.shift
|
138
|
-
else
|
139
|
-
a[k] = a[j]
|
140
|
-
j += 1
|
141
|
-
end
|
142
|
-
k += 1
|
143
|
-
count += 1
|
144
|
-
end
|
145
|
-
return count
|
146
|
-
end
|
147
|
-
|
148
|
-
# QuickSort, based on the description from Cormen et al. The interface is
|
149
|
-
# a method qsort, called with the array to sort and an optional mode parameter
|
150
|
-
# that specifies whether to count comparisons or measure execution time.
|
151
|
-
|
152
|
-
# The actual sorting is done by qs. The parameters (using notation from
|
153
|
-
# Cormen et al): p is the left boundary of the region to sort, and r is
|
154
|
-
# right boundary. The call to partition sets q, the new boundary between
|
155
|
-
# two sub-regions.
|
156
|
-
|
157
|
-
def qsort(a, mode = nil)
|
158
|
-
dup = a.clone
|
159
|
-
Timer.start
|
160
|
-
if mode == :timer
|
161
|
-
return Timer.stop
|
162
|
-
else
|
163
|
-
count = qs(dup, 0, a.length-1, mode)
|
164
|
-
return mode == :count ? count : dup
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
def qs(a, p, r, mode)
|
169
|
-
puts bracketed(a,p,r) if mode == :trace
|
170
|
-
if p < r
|
171
|
-
q, count = partition(a, p, r)
|
172
|
-
count += qs(a, p, q, mode)
|
173
|
-
count += qs(a, q+1, r, mode)
|
174
|
-
else
|
175
|
-
count = 0
|
176
|
-
end
|
177
|
-
return count
|
178
|
-
end
|
179
|
-
|
180
|
-
# Set the pivot (called x here) to the item on the left edge of the
|
181
|
-
# region, then extend the regions until they meet in the middle
|
182
|
-
|
183
|
-
def partition(a, p, r)
|
184
|
-
x = a[p]
|
185
|
-
i = p - 1
|
186
|
-
j = r + 1
|
187
|
-
count = 0
|
188
|
-
while true
|
189
|
-
loop { j = j - 1; count += 1; break if a[j] <= x }
|
190
|
-
loop { i = i + 1; count += 1; break if a[i] >= x }
|
191
|
-
if i < j
|
192
|
-
a[i], a[j] = a[j], a[i]
|
193
|
-
else
|
194
|
-
return j, count
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
def bracketed(a, left, right)
|
200
|
-
# puts "#{left}..#{right}"
|
201
|
-
tmp = []
|
202
|
-
tmp += a[ 0 .. (left-1) ] if left > 0
|
203
|
-
tmp << "["
|
204
|
-
tmp += a[ left .. right ] if right >= 0
|
205
|
-
tmp << "]"
|
206
|
-
tmp += a[ (right+1) .. (a.length-1) ] if right < a.length
|
207
|
-
return tmp.join(" ")
|
208
|
-
end
|
209
|
-
|
210
|
-
end # RecursionLab
|
211
|
-
|
212
|
-
end # RubyLabs
|
213
|
-
|
data/lib/viewer.rb
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
|
2
|
-
=begin rdoc
|
3
|
-
|
4
|
-
== Viewer
|
5
|
-
|
6
|
-
A module for displaying graphical views of objects created in lab projects. A view
|
7
|
-
is a simple drawing canvas with no controls -- objects are drawn when students evaluate
|
8
|
-
expressions in an IRB session.
|
9
|
-
|
10
|
-
The communication between IRB and the canvas is mediated by a Linda tuple-space. When
|
11
|
-
this module is included in an IRB session it launches a Ruby program named 'bb.rb', which
|
12
|
-
implements a Rinda tuplespace, and then launches a viewer program that will extract
|
13
|
-
tuples that describe objects and draw representations of those objects. There are
|
14
|
-
different viewers for each lab, e.g. nbview.rb is the N-body project viewer that draws
|
15
|
-
circles to show the positions of planets.
|
16
|
-
|
17
|
-
This organization is pretty cumbersome, but it appears to be the best/only way to control
|
18
|
-
a graphical interface from an IRB session. Ideally IRB could create a canvas from a GUI
|
19
|
-
library like Tk or Wx, but the problem is that these libraries only update their widgets
|
20
|
-
from a top-level event loop. In Ruby 1.8, without native threads, the event loop doesn't
|
21
|
-
give control back to IRB. Launching a Wx-based viewer as a separate application and
|
22
|
-
communicating with it via Linda is working, but is not very responsive. For one-way
|
23
|
-
communication it seems to be adequate.
|
24
|
-
|
25
|
-
The code assumes the module is loaded by a require statement in a lab method that is called
|
26
|
-
to initialize a view for that lab. Since the code is loaded by a require the module is
|
27
|
-
loaded only once. Statements in the main body of the module set up the bulletin board
|
28
|
-
and do other one-time intializations.
|
29
|
-
|
30
|
-
=end
|
31
|
-
|
32
|
-
require 'drb/drb'
|
33
|
-
require 'rinda/tuplespace'
|
34
|
-
|
35
|
-
module RubyLabs
|
36
|
-
|
37
|
-
module Viewer
|
38
|
-
|
39
|
-
# Code to execute when the module is loaded (assumed to happen only once):
|
40
|
-
|
41
|
-
raise "for interactive use only" unless defined? IRB
|
42
|
-
|
43
|
-
DRb.start_service # ? was after launch of bb.rb
|
44
|
-
|
45
|
-
@@uri = "druby://localhost:53783"
|
46
|
-
@@bindir = File.join(File.dirname(__FILE__), '..', 'bin')
|
47
|
-
@@bb = IO.popen("#{@@bindir}/bb.rb")
|
48
|
-
@@ts = Rinda::TupleSpaceProxy.new(DRbObject.new(nil, @@uri))
|
49
|
-
|
50
|
-
at_exit do
|
51
|
-
Process.kill(9, @@bb.pid)
|
52
|
-
Process.kill(9, @@viewer.pid)
|
53
|
-
end
|
54
|
-
|
55
|
-
def write_tuple(tag, args)
|
56
|
-
puts "RubyLabs::Viewer::write_tuple #{tag} #{args} #{@@uri}"
|
57
|
-
end
|
58
|
-
|
59
|
-
def launch_viewer(name)
|
60
|
-
@@viewer = IO.popen("#{@@bindir}/#{name} #{@@uri}")
|
61
|
-
end
|
62
|
-
|
63
|
-
end # Viewer
|
64
|
-
|
65
|
-
end # RubyLabs
|