rubylabs 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +15 -6
- data/Rakefile +3 -0
- data/VERSION +1 -1
- data/lib/bitlab.rb +593 -328
- data/lib/demos.rb +20 -9
- data/lib/elizalab.rb +660 -507
- data/lib/hashlab.rb +289 -192
- data/lib/introlab.rb +33 -38
- data/lib/iterationlab.rb +117 -61
- data/lib/marslab.rb +608 -475
- data/lib/randomlab.rb +227 -121
- data/lib/recursionlab.rb +197 -140
- data/lib/rubylabs.rb +936 -390
- data/lib/sievelab.rb +32 -24
- data/lib/spherelab.rb +308 -220
- data/lib/tsplab.rb +634 -312
- data/test/bit_test.rb +4 -4
- data/test/tsp_test.rb +18 -0
- metadata +2 -2
data/lib/randomlab.rb
CHANGED
@@ -1,58 +1,104 @@
|
|
1
|
+
module RubyLabs
|
1
2
|
|
2
3
|
=begin rdoc
|
3
4
|
|
4
5
|
== RandomLab
|
5
6
|
|
6
|
-
|
7
|
-
|
8
|
-
|
7
|
+
The RandomLab module has definitions of classes and methods used in the projects for Chapter 9
|
8
|
+
of <em>Explorations in Computing</em>. The module has methods used in experiments with pseudorandom
|
9
|
+
number generators.
|
9
10
|
|
10
|
-
=begin
|
11
|
-
TODO number line -- mini-histogram, e.g. second tick drawn above first? else explain in lab manual / reference why two values per tickmark
|
12
|
-
TODO another thing for documentation: diff between p.random(x,y) and random(x,y) [latter uses Ruby's PRNG]
|
13
11
|
=end
|
14
|
-
|
15
|
-
module RubyLabs
|
16
|
-
|
12
|
+
|
17
13
|
module RandomLab
|
18
14
|
|
19
15
|
require "permute.rb"
|
20
16
|
|
17
|
+
NumberLine = Struct.new(:line, :npoints, :options)
|
18
|
+
Histogram = Struct.new(:bins, :max, :keys, :counts, :base, :options)
|
19
|
+
DotPlot = Struct.new(:max, :options)
|
20
|
+
|
21
|
+
@@numberLineOptions = {
|
22
|
+
:lineThickness => 3,
|
23
|
+
:lineColor => '#777777',
|
24
|
+
:tickHeight => 20,
|
25
|
+
:tickWidth => 1,
|
26
|
+
:tickColor => '#0000FF',
|
27
|
+
}
|
28
|
+
|
29
|
+
@@histogramOptions = {
|
30
|
+
:binColor => '#000080',
|
31
|
+
:boxIncrement => 8.0,
|
32
|
+
:rescaleTrigger => 50,
|
33
|
+
}
|
34
|
+
|
35
|
+
@@dotPlotOptions = {
|
36
|
+
:dotColor => '#000080',
|
37
|
+
:dotRadius => 1.0,
|
38
|
+
}
|
39
|
+
|
40
|
+
@@drawing = nil
|
41
|
+
@@delay = 0.01
|
42
|
+
|
21
43
|
=begin rdoc
|
22
|
-
Pseudo-random number generator. Constraints on a, c, and m:
|
23
|
-
* c and m must be relatively prime
|
24
|
-
* a-1 divisible by prime factors of m
|
25
|
-
* if m is multiple of 4, a-1 must also be a multiple of 4
|
26
44
|
|
27
|
-
|
28
|
-
|
45
|
+
== PRNG
|
46
|
+
|
47
|
+
A PRNG object is a pseudorandom number generator based on the mixed congruential method.
|
48
|
+
Sequences generated by a PRNG are defined by three constants, named +a+, +c+, and +m+.
|
49
|
+
If <tt>x[i]</tt> is the current item in the sequence, the equation for the next item
|
50
|
+
<tt>x[i+1]</tt> is
|
51
|
+
x[i+1] = (a * x[i] + c) % m
|
52
|
+
|
29
53
|
=end
|
30
54
|
|
31
55
|
class PRNG
|
32
56
|
|
33
57
|
attr_accessor :a, :c, :m, :x
|
34
58
|
|
59
|
+
# Make a new pseudorandom number generator using constants +a+, +c+, and +m+.
|
60
|
+
#
|
61
|
+
# Example -- a random number generator that has the full period of m = 1000 but some
|
62
|
+
# surprising correlations between successive values:
|
63
|
+
# p = PRNG.new(81, 337, 1000)
|
64
|
+
# => #<RandomLab::PRNG a: 81 c: 337 m: 1000>
|
65
|
+
#
|
66
|
+
# Example: a better PRNG, using values suggested in <em>Numerical Recipes</em> (Press, et al):
|
67
|
+
# >> p = PRNG.new(171, 11213, 53125)
|
68
|
+
# => #<RandomLab::PRNG a: 171 c: 11213 m: 53125>
|
69
|
+
|
35
70
|
def initialize(a, c, m)
|
36
71
|
@a = a
|
37
72
|
@c = c
|
38
73
|
@m = m
|
39
74
|
@x = 0
|
40
75
|
end
|
76
|
+
|
77
|
+
# Return the current item in the pseudorandom sequence (the most recently generated random
|
78
|
+
# number).
|
41
79
|
|
42
80
|
def state
|
43
81
|
return @x
|
44
82
|
end
|
83
|
+
|
84
|
+
# Set the state of the pseudorandom sequence to +val+.
|
45
85
|
|
46
86
|
def seed(val)
|
47
87
|
@x = val
|
48
88
|
end
|
49
|
-
|
89
|
+
|
90
|
+
# Get the next pseudorandom number in the sequence defined by this PRNG object.
|
91
|
+
#--
|
50
92
|
# :begin :advance
|
51
93
|
def advance
|
52
94
|
@x = (@x * @a + @c) % @m
|
53
95
|
end
|
54
96
|
# :end :advance
|
55
97
|
|
98
|
+
# Get a random integer between +min+ and +max+ from this PRNG object. Calls
|
99
|
+
# advance the get the next value from the pseudorandom sequence, then maps it
|
100
|
+
# to an integer between +min+ and +max+.
|
101
|
+
#--
|
56
102
|
# :begin :random
|
57
103
|
def random(min, max)
|
58
104
|
return nil if max <= min
|
@@ -61,6 +107,7 @@ module RandomLab
|
|
61
107
|
end
|
62
108
|
# :end :random
|
63
109
|
|
110
|
+
# Create a string that describes the attributes of this PRNG object.
|
64
111
|
def inspect
|
65
112
|
sprintf "#<RandomLab::PRNG a: #{@a} c: #{@c} m: #{@m}>"
|
66
113
|
end
|
@@ -69,7 +116,12 @@ module RandomLab
|
|
69
116
|
|
70
117
|
end # class PRNG
|
71
118
|
|
72
|
-
#
|
119
|
+
# Return an array of +m+ numbers defined by the pseudorandom sequence with
|
120
|
+
# parameters +a+, +c+, and +m+. The first number in the sequence is 0, and
|
121
|
+
# the remaining numbers are defined by the recurrence
|
122
|
+
# x[i+1] = (a * x[i] + c) % m
|
123
|
+
#--
|
124
|
+
# :begin :prng_sequence
|
73
125
|
def prng_sequence(a, c, m)
|
74
126
|
seq = [0]
|
75
127
|
(m-1).times do
|
@@ -77,35 +129,34 @@ module RandomLab
|
|
77
129
|
end
|
78
130
|
return seq
|
79
131
|
end
|
80
|
-
# :end :prng_sequence
|
81
|
-
|
82
|
-
=begin rdoc
|
83
|
-
Make a new deck of cards
|
84
|
-
=end
|
132
|
+
# :end :prng_sequence
|
85
133
|
|
134
|
+
# Make a new deck of cards. Returns an array of 52 card objects, arranged
|
135
|
+
# in order from card #0 (the ace of spades) through card #51 (the two of clubs).
|
136
|
+
|
86
137
|
def new_deck
|
87
138
|
(0..51).map { |i| Card.new(i) }
|
88
139
|
end
|
89
140
|
|
90
141
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
142
|
+
# Compute the probability of a duplicate item in a collection of +n+ items
|
143
|
+
# drawn from the range [1..d].
|
144
|
+
#
|
145
|
+
# Example -- to compute the
|
146
|
+
# probability of drawing the same card twice when sampling with replacement
|
147
|
+
# 5 times from a deck of 52 cards:
|
148
|
+
# >> pdup(5, 52)
|
149
|
+
# => 0.179716221420819
|
97
150
|
|
98
151
|
def pdup(n, d)
|
99
152
|
return 1.0 if n > d
|
100
153
|
return 1.0 - (1..(n-1)).inject(1.0) { |p, k| p * (1.0 - (k / 52.0)) }
|
101
154
|
end
|
102
155
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
# Note: permute! moved to own source file, permute.rb
|
156
|
+
# A helper method intended to be called via a probe to print the contents
|
157
|
+
# of an array during the execution of the <tt>permute!</tt> method. The arguments
|
158
|
+
# are the array to display, the location of a left bracket, and the item
|
159
|
+
# location where the item next to the bracket will be moved on the next swap.
|
109
160
|
|
110
161
|
def brackets(a, i, r)
|
111
162
|
res = "#{r}: "
|
@@ -121,19 +172,17 @@ module RandomLab
|
|
121
172
|
return res
|
122
173
|
end
|
123
174
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
=end
|
136
|
-
|
175
|
+
# Given an array of 5 Card objects, determine what type of poker hand is
|
176
|
+
# represented by the cards. The return value is a symbol, e.g. <tt>:pair</tt>,
|
177
|
+
# <tt>:full_house</tt>, etc. (call poker_rankings to see the complete list of
|
178
|
+
# symbols).
|
179
|
+
#
|
180
|
+
# Example (assuming +d+ is a complete deck of 52 Card objects):
|
181
|
+
# >> h = permute!(d).first(5)
|
182
|
+
# => [AH, 6S, 7C, JH, AC]
|
183
|
+
# >> poker_rank(h)
|
184
|
+
# => :pair
|
185
|
+
|
137
186
|
def poker_rank(a)
|
138
187
|
rcount = Array.new(Card::Ranks.length, 0)
|
139
188
|
scount = Array.new(Card::Suits.length, 0)
|
@@ -158,28 +207,35 @@ module RandomLab
|
|
158
207
|
return :pair
|
159
208
|
end
|
160
209
|
end
|
210
|
+
|
211
|
+
# Return a list of symbols used to classify poker hands.
|
161
212
|
|
162
213
|
def poker_rankings
|
163
214
|
return [:high_card, :pair, :two_pair, :three_of_a_kind, :straight, :flush, :full_house, :four_of_a_kind, :straight_flush]
|
164
215
|
end
|
165
216
|
|
217
|
+
# Initialize a Hash object with keys that are poker rank symbols and values that are all initially 0.
|
218
|
+
# Used in experiments that count the number of times various hands are dealt.
|
219
|
+
#
|
220
|
+
# Example:
|
221
|
+
# >> poker_counts
|
222
|
+
# => {:flush=>0, :full_house=>0, ... :high_card=>0}
|
223
|
+
|
166
224
|
def poker_counts
|
167
225
|
h = Hash.new
|
168
226
|
poker_rankings.each { |x| h[x] = 0 }
|
169
227
|
return h
|
170
228
|
end
|
171
229
|
|
172
|
-
|
173
230
|
=begin rdoc
|
174
|
-
Class to represent cards from a standard 52-card deck. Includes comparators
|
175
|
-
to sort by rank or suit.
|
176
|
-
|
177
|
-
Call Card.new to get a random card, or Card.new(id) to get a specific card
|
178
|
-
where id is a number between 0 and 51.
|
179
|
-
=end
|
180
231
|
|
181
|
-
|
182
|
-
|
232
|
+
== Card
|
233
|
+
|
234
|
+
A Card object represents a single card from a standard 52-card deck. The two
|
235
|
+
attributes of a card are its rank (represented by a symbol such as :ace, :king, :three, etc)
|
236
|
+
and its suit (:spades, :hearts, etc).
|
237
|
+
|
238
|
+
=end
|
183
239
|
|
184
240
|
class Card
|
185
241
|
attr_accessor :rank, :suit
|
@@ -192,16 +248,43 @@ module RandomLab
|
|
192
248
|
Ranks = [:ace, :king, :queen, :jack, :ten, :nine, :eight, :seven, :six, :five, :four, :three, :two]
|
193
249
|
end
|
194
250
|
|
251
|
+
# Create a new Card object. Cards are ordered from 0 to 51, with 0 being the ace of spades
|
252
|
+
# and 51 being the two of clubs. If no argument is passed to new, a random card is chosen.
|
253
|
+
# If an +id+ between 0 and 51 is passed the specified card is created.
|
254
|
+
#
|
255
|
+
# Example:
|
256
|
+
# >> Card.new
|
257
|
+
# => 5H
|
258
|
+
# >> Card.new(0)
|
259
|
+
# => AS
|
260
|
+
# >> Card.new(1)
|
261
|
+
# => KS
|
262
|
+
# >> Card.new(51)
|
263
|
+
# => 2C
|
264
|
+
|
195
265
|
def initialize(id = nil)
|
196
266
|
id = rand(52) if id.nil?
|
197
267
|
raise "card must be between 0 and 51" if id < 0 || id > 51
|
198
268
|
@suit = Suits[id / 13]
|
199
269
|
@rank = Ranks[id % 13]
|
200
270
|
end
|
271
|
+
|
272
|
+
# Compare this Card with Card x. Two cards are equal if they have the same
|
273
|
+
# suit and same rank.
|
201
274
|
|
202
275
|
def ==(x)
|
203
276
|
return @suit == x.suit && @rank == x.rank
|
204
277
|
end
|
278
|
+
|
279
|
+
# Define the sort ordering for Card objects. Cards are compared first by suit,
|
280
|
+
# and then by rank. The result of sorting a hand (and array of Card objects) is
|
281
|
+
# the common situation for most card games, where cards are grouped by suit.
|
282
|
+
#
|
283
|
+
# Example (assuming +d+ is a complete deck of 52 cards):
|
284
|
+
# >> h = permute!(d).first(13)
|
285
|
+
# => [2C, QS, 8S, 6C, 10H, JS, AD, AS, 7D, 8D, JC, 4C, AH]
|
286
|
+
# >> h.sort
|
287
|
+
# => [AS, QS, JS, 8S, AH, 10H, AD, 8D, 7D, JC, 6C, 4C, 2C]
|
205
288
|
|
206
289
|
def <=>(x)
|
207
290
|
r0 = Ranks.index(@rank); r1 = Ranks.index(x.rank)
|
@@ -215,6 +298,11 @@ module RandomLab
|
|
215
298
|
|
216
299
|
@@outputform = :utf8
|
217
300
|
|
301
|
+
# Make a string to display a Card objects on the terminal. Checks
|
302
|
+
# Ruby's $KCODE global variable to see if the system is using UTF-8. If so, the code for a glyph that
|
303
|
+
# shows a spade, heart, diamond, or club is inserted into the string, otherwise a letter is
|
304
|
+
# used.
|
305
|
+
|
218
306
|
def inspect
|
219
307
|
s = ""
|
220
308
|
s << case @rank
|
@@ -252,7 +340,6 @@ module RandomLab
|
|
252
340
|
end
|
253
341
|
end
|
254
342
|
return s
|
255
|
-
# "#{@rank} #{@suit}"
|
256
343
|
end
|
257
344
|
|
258
345
|
alias to_s inspect
|
@@ -267,21 +354,18 @@ module RandomLab
|
|
267
354
|
|
268
355
|
end # class Card
|
269
356
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
plot_point(x,y) add a dot at (x,y) to the dotplot
|
283
|
-
=end
|
284
|
-
|
357
|
+
# Initialize the RubyLabs Canvas with a drawing of a number line for integers from 0 to +npoints+-1.
|
358
|
+
# Options that control the appearance of the display, and their default values, are:
|
359
|
+
# :lineThickness => 3
|
360
|
+
# :lineColor => '#777777'
|
361
|
+
# :tickHeight => 20
|
362
|
+
# :tickWidth => 1
|
363
|
+
# :tickColor => '#0000FF'
|
364
|
+
#
|
365
|
+
# Example:
|
366
|
+
# >> view_numberline(500, :lineColor => 'blue', :lineThickness => 1)
|
367
|
+
# => true
|
368
|
+
|
285
369
|
def view_numberline(npoints, userOptions = {})
|
286
370
|
Canvas.init(500, 100, "RandomLab::NumberLine")
|
287
371
|
options = @@numberLineOptions.merge(userOptions)
|
@@ -290,21 +374,48 @@ module RandomLab
|
|
290
374
|
return true
|
291
375
|
end
|
292
376
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
377
|
+
# Draw a tick mark on the RubyLabs Canvas, provided the canvas has been initialized with a call to
|
378
|
+
# view_numberline.
|
379
|
+
|
380
|
+
def tick_mark(i)
|
381
|
+
if @@drawing.class != NumberLine
|
382
|
+
puts "call view_numberline to initialize the number line"
|
383
|
+
elsif i < 0 || i >= @@drawing.npoints
|
384
|
+
puts "tick_mark: 0 <= i < #{@@drawing.npoints}"
|
385
|
+
else
|
386
|
+
x0, y0, x1, y1 = @@drawing.line.coords
|
387
|
+
tx = (i.to_f / @@drawing.npoints) * (x1-x0)
|
388
|
+
ty = y0 - @@drawing.options[:tickHeight]
|
389
|
+
Canvas::Line.new(tx, y0, tx, ty, :width => @@drawing.options[:tickWidth], :fill => @@drawing.options[:tickColor])
|
390
|
+
sleep(@@delay)
|
391
|
+
end
|
392
|
+
return true
|
393
|
+
end
|
394
|
+
|
395
|
+
# Initialize the RubyLabs Canvas to show a histogram with the specified bins. In the
|
396
|
+
# initial drawing each bin is represented by a rectangle one pixel tall, i.e. a horizontal line.
|
397
|
+
# As items are added to a bin the rectangle will grow in height. If any rectangle reaches the
|
398
|
+
# maximum height, all the rectangles are rescaled so the bins can continue to grow.
|
399
|
+
#
|
400
|
+
# The argument to view_histogram can either be an integer, which specifies the number of bins,
|
401
|
+
# or an array of symbols, in which case there will be one bin for each symbol. If the argument is an integer,
|
402
|
+
# a second argument can specify a maximum data value; for example, calling <tt>view_histogram(10,100)</tt>
|
403
|
+
# will make a histogram with 10 bins for numbers between 0 and 99, so that data values 0 through
|
404
|
+
# 9 will go in the first bin, 10 through 19 in the second bin, and so on.
|
405
|
+
#
|
406
|
+
# Display options and their default values are:
|
407
|
+
# :binColor => '#000080'
|
408
|
+
# :boxIncrement => 8.0
|
409
|
+
# :rescaleTrigger => 50
|
410
|
+
#
|
411
|
+
# Example: make a histogram for the numbers between 0 and 5:
|
412
|
+
# >> view_histogram(6)
|
413
|
+
# => true
|
414
|
+
# Example: make a histogram to count the number of times each type of poker hand is seen in an
|
415
|
+
# experiment:
|
416
|
+
# >> view_histogram(poker_rankings, :binColor => 'darkgreen')
|
417
|
+
# => true
|
418
|
+
|
308
419
|
def view_histogram(*args)
|
309
420
|
begin
|
310
421
|
if args[0].class == Array
|
@@ -341,7 +452,10 @@ module RandomLab
|
|
341
452
|
|
342
453
|
return true
|
343
454
|
end
|
344
|
-
|
455
|
+
|
456
|
+
# Update the bin for data item +x+, presuming the RubyLabs Canvas has been initialized to show
|
457
|
+
# a histogram for data of this type. The bin for +x+ increases in height. If it reaches
|
458
|
+
# the maximum height, rescale all the bins and increase the maximum height.
|
345
459
|
|
346
460
|
def update_bin(x)
|
347
461
|
if @@drawing.class != Histogram
|
@@ -380,6 +494,8 @@ module RandomLab
|
|
380
494
|
sleep(@@delay)
|
381
495
|
return true
|
382
496
|
end
|
497
|
+
|
498
|
+
# Return an array of counts for the bins in the histogram currently on the RubyLabs Canvas.
|
383
499
|
|
384
500
|
def get_counts
|
385
501
|
if @@drawing.class == Histogram
|
@@ -389,55 +505,45 @@ module RandomLab
|
|
389
505
|
return nil
|
390
506
|
end
|
391
507
|
end
|
392
|
-
|
508
|
+
|
509
|
+
# Initialize the RubyLabs Canvas to show a dot plot with +npoints+ in both the +x+
|
510
|
+
# and +y+ dimension. Drawing options and their defaults are
|
511
|
+
# :dotColor => '#000080'
|
512
|
+
# :dotRadius => 1.0
|
513
|
+
#
|
514
|
+
# Example: intialize the drawing for a 250 x 250 dot plot with green dots:
|
515
|
+
# >> view_dotplot(250, :dotColor => 'darkgreen')
|
516
|
+
# => true
|
517
|
+
|
393
518
|
def view_dotplot(npoints, userOptions = {})
|
394
519
|
Canvas.init(500, 500, "RandomLab::DotPlot")
|
395
520
|
options = @@dotPlotOptions.merge(userOptions)
|
396
521
|
@@drawing = DotPlot.new(npoints, options)
|
397
522
|
return true
|
398
523
|
end
|
524
|
+
|
525
|
+
# Add a point at location 'x', 'y' to the dot plot on the RubyLabs Canvas.
|
526
|
+
#
|
527
|
+
# Example: if the canvas was initialized to show a 250 x 250 plot, this call
|
528
|
+
# will display a point in the center of the drawing:
|
529
|
+
# >> plot_point(125,125)
|
530
|
+
# => nil
|
399
531
|
|
400
532
|
def plot_point(x,y)
|
401
533
|
if @@drawing.class != DotPlot
|
402
534
|
puts "call view_dotplot to initialize a dot plot"
|
403
|
-
|
404
|
-
|
405
|
-
|
535
|
+
elsif x < 0 || x >= @@drawing.max || y < 0 || y >= @@drawing.max
|
536
|
+
puts "plot_point: 0 <= x, y < #{@@drawing.max}"
|
537
|
+
else
|
406
538
|
px = (x.to_f / @@drawing.max) * Canvas.width
|
407
539
|
py = (y.to_f / @@drawing.max) * Canvas.height
|
408
540
|
r = @@drawing.options[:dotRadius]
|
409
541
|
color = @@drawing.options[:dotColor]
|
410
542
|
Canvas::Circle.new( px, py, r, :outline => color, :fill => color )
|
411
|
-
|
412
|
-
|
543
|
+
end
|
544
|
+
return nil
|
413
545
|
end
|
414
|
-
|
415
|
-
NumberLine = Struct.new(:line, :npoints, :options)
|
416
|
-
Histogram = Struct.new(:bins, :max, :keys, :counts, :base, :options)
|
417
|
-
DotPlot = Struct.new(:max, :options)
|
418
|
-
|
419
|
-
@@numberLineOptions = {
|
420
|
-
:lineThickness => 3,
|
421
|
-
:lineColor => '#777777',
|
422
|
-
:tickHeight => 20,
|
423
|
-
:tickWidth => 1,
|
424
|
-
:tickColor => '#0000FF',
|
425
|
-
}
|
426
|
-
|
427
|
-
@@histogramOptions = {
|
428
|
-
:binColor => '#000080',
|
429
|
-
:boxIncrement => 8.0,
|
430
|
-
:rescaleTrigger => 50,
|
431
|
-
}
|
432
|
-
|
433
|
-
@@dotPlotOptions = {
|
434
|
-
:dotColor => '#000080',
|
435
|
-
:dotRadius => 1.0,
|
436
|
-
}
|
437
|
-
|
438
|
-
@@drawing = nil
|
439
|
-
@@delay = 0.01
|
440
|
-
|
546
|
+
|
441
547
|
end # RandomLab
|
442
548
|
|
443
549
|
end # RubyLabs
|