rubysl-set 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +0 -1
  3. data/.travis.yml +8 -0
  4. data/README.md +2 -2
  5. data/Rakefile +0 -1
  6. data/lib/rubysl/set.rb +2 -0
  7. data/lib/rubysl/set/set.rb +1237 -0
  8. data/lib/{rubysl-set → rubysl/set}/version.rb +1 -1
  9. data/lib/set.rb +1 -0
  10. data/rubysl-set.gemspec +19 -18
  11. data/spec/add_spec.rb +26 -0
  12. data/spec/append_spec.rb +6 -0
  13. data/spec/classify_spec.rb +34 -0
  14. data/spec/clear_spec.rb +16 -0
  15. data/spec/collect_spec.rb +6 -0
  16. data/spec/constructor_spec.rb +14 -0
  17. data/spec/delete_if_spec.rb +45 -0
  18. data/spec/delete_spec.rb +36 -0
  19. data/spec/difference_spec.rb +6 -0
  20. data/spec/divide_spec.rb +33 -0
  21. data/spec/each_spec.rb +33 -0
  22. data/spec/empty_spec.rb +9 -0
  23. data/spec/enumerable/to_set_spec.rb +18 -0
  24. data/spec/eql_spec.rb +16 -0
  25. data/spec/equal_value_spec.rb +37 -0
  26. data/spec/exclusion_spec.rb +17 -0
  27. data/spec/flatten_merge_spec.rb +22 -0
  28. data/spec/flatten_spec.rb +39 -0
  29. data/spec/hash_spec.rb +14 -0
  30. data/spec/include_spec.rb +6 -0
  31. data/spec/initialize_copy_spec.rb +17 -0
  32. data/spec/initialize_spec.rb +23 -0
  33. data/spec/inspect_spec.rb +17 -0
  34. data/spec/intersection_spec.rb +10 -0
  35. data/spec/keep_if_spec.rb +39 -0
  36. data/spec/length_spec.rb +6 -0
  37. data/spec/map_spec.rb +6 -0
  38. data/spec/member_spec.rb +6 -0
  39. data/spec/merge_spec.rb +18 -0
  40. data/spec/minus_spec.rb +6 -0
  41. data/spec/plus_spec.rb +6 -0
  42. data/spec/pretty_print_cycle_spec.rb +9 -0
  43. data/spec/pretty_print_spec.rb +16 -0
  44. data/spec/proper_subset_spec.rb +33 -0
  45. data/spec/proper_superset_spec.rb +33 -0
  46. data/spec/reject_spec.rb +49 -0
  47. data/spec/replace_spec.rb +16 -0
  48. data/spec/select_spec.rb +43 -0
  49. data/spec/shared/add.rb +14 -0
  50. data/spec/shared/collect.rb +20 -0
  51. data/spec/shared/difference.rb +15 -0
  52. data/spec/shared/include.rb +7 -0
  53. data/spec/shared/intersection.rb +15 -0
  54. data/spec/shared/length.rb +6 -0
  55. data/spec/shared/union.rb +15 -0
  56. data/spec/size_spec.rb +6 -0
  57. data/spec/sortedset/add_spec.rb +34 -0
  58. data/spec/sortedset/append_spec.rb +6 -0
  59. data/spec/sortedset/classify_spec.rb +34 -0
  60. data/spec/sortedset/clear_spec.rb +16 -0
  61. data/spec/sortedset/collect_spec.rb +6 -0
  62. data/spec/sortedset/constructor_spec.rb +14 -0
  63. data/spec/sortedset/delete_if_spec.rb +47 -0
  64. data/spec/sortedset/delete_spec.rb +36 -0
  65. data/spec/sortedset/difference_spec.rb +6 -0
  66. data/spec/sortedset/divide_spec.rb +33 -0
  67. data/spec/sortedset/each_spec.rb +35 -0
  68. data/spec/sortedset/empty_spec.rb +9 -0
  69. data/spec/sortedset/eql_spec.rb +17 -0
  70. data/spec/sortedset/equal_value_spec.rb +12 -0
  71. data/spec/sortedset/exclusion_spec.rb +17 -0
  72. data/spec/sortedset/flatten_merge_spec.rb +7 -0
  73. data/spec/sortedset/flatten_spec.rb +47 -0
  74. data/spec/sortedset/hash_spec.rb +14 -0
  75. data/spec/sortedset/include_spec.rb +6 -0
  76. data/spec/sortedset/initialize_copy_spec.rb +17 -0
  77. data/spec/sortedset/initialize_spec.rb +31 -0
  78. data/spec/sortedset/inspect_spec.rb +9 -0
  79. data/spec/sortedset/intersection_spec.rb +10 -0
  80. data/spec/sortedset/keep_if_spec.rb +32 -0
  81. data/spec/sortedset/length_spec.rb +6 -0
  82. data/spec/sortedset/map_spec.rb +6 -0
  83. data/spec/sortedset/member_spec.rb +6 -0
  84. data/spec/sortedset/merge_spec.rb +18 -0
  85. data/spec/sortedset/minus_spec.rb +6 -0
  86. data/spec/sortedset/plus_spec.rb +6 -0
  87. data/spec/sortedset/pretty_print_cycle_spec.rb +9 -0
  88. data/spec/sortedset/pretty_print_spec.rb +16 -0
  89. data/spec/sortedset/proper_subset_spec.rb +32 -0
  90. data/spec/sortedset/proper_superset_spec.rb +32 -0
  91. data/spec/sortedset/reject_spec.rb +51 -0
  92. data/spec/sortedset/replace_spec.rb +16 -0
  93. data/spec/sortedset/select_spec.rb +36 -0
  94. data/spec/sortedset/shared/add.rb +14 -0
  95. data/spec/sortedset/shared/collect.rb +20 -0
  96. data/spec/sortedset/shared/difference.rb +15 -0
  97. data/spec/sortedset/shared/include.rb +7 -0
  98. data/spec/sortedset/shared/intersection.rb +15 -0
  99. data/spec/sortedset/shared/length.rb +6 -0
  100. data/spec/sortedset/shared/union.rb +15 -0
  101. data/spec/sortedset/size_spec.rb +6 -0
  102. data/spec/sortedset/subset_spec.rb +32 -0
  103. data/spec/sortedset/subtract_spec.rb +16 -0
  104. data/spec/sortedset/superset_spec.rb +32 -0
  105. data/spec/sortedset/to_a_spec.rb +7 -0
  106. data/spec/sortedset/union_spec.rb +10 -0
  107. data/spec/subset_spec.rb +33 -0
  108. data/spec/subtract_spec.rb +16 -0
  109. data/spec/superset_spec.rb +33 -0
  110. data/spec/to_a_spec.rb +7 -0
  111. data/spec/union_spec.rb +10 -0
  112. metadata +282 -86
  113. data/lib/rubysl-set.rb +0 -7
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f85297c049ae95b1ab859180e5f81b7653583a52
4
+ data.tar.gz: a308eaf5aa2d518adfa3d470e3d3a8b371e63034
5
+ SHA512:
6
+ metadata.gz: 39cfe578a80a017ab3acc64cc15b2f86f88ef13b69d215083f0c571240c3d1fbbfa5a604f8dcc9797d2c51cada18e0c90c29edc2301f5465baed1c5b8df9a4f0
7
+ data.tar.gz: c56fb177f7687686f866f29cd2612dd33a461f654fb2dd8b2dd31d801ec1b930fb794f818f026d811f8d7431a2eec4ae46eed10b115c34cdaeb66b3e30f4b380
data/.gitignore CHANGED
@@ -15,4 +15,3 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
- .rbx
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ before_install:
3
+ - gem update --system
4
+ - gem --version
5
+ - gem install rubysl-bundler
6
+ script: bundle exec mspec spec
7
+ rvm:
8
+ - rbx-nightly-18mode
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # RubySL::Set
1
+ # Rubysl::Set
2
2
 
3
3
  TODO: Write a gem description
4
4
 
@@ -24,6 +24,6 @@ TODO: Write usage instructions here
24
24
 
25
25
  1. Fork it
26
26
  2. Create your feature branch (`git checkout -b my-new-feature`)
27
- 3. Commit your changes (`git commit -am 'Added some feature'`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
28
  4. Push to the branch (`git push origin my-new-feature`)
29
29
  5. Create new Pull Request
data/Rakefile CHANGED
@@ -1,2 +1 @@
1
- #!/usr/bin/env rake
2
1
  require "bundler/gem_tasks"
data/lib/rubysl/set.rb ADDED
@@ -0,0 +1,2 @@
1
+ require "rubysl/set/set"
2
+ require "rubysl/set/version"
@@ -0,0 +1,1237 @@
1
+ #!/usr/bin/env ruby
2
+ #--
3
+ # set.rb - defines the Set class
4
+ #++
5
+ # Copyright (c) 2002-2008 Akinori MUSHA <knu@iDaemons.org>
6
+ #
7
+ # Documentation by Akinori MUSHA and Gavin Sinclair.
8
+ #
9
+ # All rights reserved. You can redistribute and/or modify it under the same
10
+ # terms as Ruby.
11
+ #
12
+ # $Id: set.rb 17051 2008-06-09 09:20:43Z knu $
13
+ #
14
+ # == Overview
15
+ #
16
+ # This library provides the Set class, which deals with a collection
17
+ # of unordered values with no duplicates. It is a hybrid of Array's
18
+ # intuitive inter-operation facilities and Hash's fast lookup. If you
19
+ # need to keep values ordered, use the SortedSet class.
20
+ #
21
+ # The method +to_set+ is added to Enumerable for convenience.
22
+ #
23
+ # See the Set class for an example of usage.
24
+
25
+
26
+ #
27
+ # Set implements a collection of unordered values with no duplicates.
28
+ # This is a hybrid of Array's intuitive inter-operation facilities and
29
+ # Hash's fast lookup.
30
+ #
31
+ # Several methods accept any Enumerable object (implementing +each+)
32
+ # for greater flexibility: new, replace, merge, subtract, |, &, -, ^.
33
+ #
34
+ # The equality of each couple of elements is determined according to
35
+ # Object#eql? and Object#hash, since Set uses Hash as storage.
36
+ #
37
+ # Finally, if you are using class Set, you can also use Enumerable#to_set
38
+ # for convenience.
39
+ #
40
+ # == Example
41
+ #
42
+ # require 'set'
43
+ # s1 = Set.new [1, 2] # -> #<Set: {1, 2}>
44
+ # s2 = [1, 2].to_set # -> #<Set: {1, 2}>
45
+ # s1 == s2 # -> true
46
+ # s1.add("foo") # -> #<Set: {1, 2, "foo"}>
47
+ # s1.merge([2, 6]) # -> #<Set: {6, 1, 2, "foo"}>
48
+ # s1.subset? s2 # -> false
49
+ # s2.subset? s1 # -> true
50
+ #
51
+ # == Contact
52
+ #
53
+ # - Akinori MUSHA <knu@iDaemons.org> (current maintainer)
54
+ #
55
+ class Set
56
+ include Enumerable
57
+
58
+ # Creates a new set containing the given objects.
59
+ def self.[](*ary)
60
+ new(ary)
61
+ end
62
+
63
+ # Creates a new set containing the elements of the given enumerable
64
+ # object.
65
+ #
66
+ # If a block is given, the elements of enum are preprocessed by the
67
+ # given block.
68
+ def initialize(enum = nil, &block) # :yields: o
69
+ @hash ||= Hash.new
70
+
71
+ return if enum.nil?
72
+
73
+ if block
74
+ enum.each { |o| add(block[o]) }
75
+ else
76
+ merge(enum)
77
+ end
78
+ end
79
+
80
+ # Copy internal hash.
81
+ def initialize_copy(orig)
82
+ @hash = orig.instance_eval{@hash}.dup
83
+ end
84
+
85
+ # Returns the number of elements.
86
+ def size
87
+ @hash.size
88
+ end
89
+ alias length size
90
+
91
+ # Returns true if the set contains no elements.
92
+ def empty?
93
+ @hash.empty?
94
+ end
95
+
96
+ # Removes all elements and returns self.
97
+ def clear
98
+ @hash.clear
99
+ self
100
+ end
101
+
102
+ # Replaces the contents of the set with the contents of the given
103
+ # enumerable object and returns self.
104
+ def replace(enum)
105
+ if enum.class == self.class
106
+ @hash.replace(enum.instance_eval { @hash })
107
+ else
108
+ raise ArgumentError, "value must be enumerable" unless enum.is_a?(Enumerable)
109
+ clear
110
+ enum.each { |o| add(o) }
111
+ end
112
+
113
+ self
114
+ end
115
+
116
+ # Converts the set to an array. The order of elements is uncertain.
117
+ def to_a
118
+ @hash.keys
119
+ end
120
+
121
+ def flatten_merge(set, seen = Set.new)
122
+ set.each { |e|
123
+ if e.is_a?(Set)
124
+ if seen.include?(e_id = e.object_id)
125
+ raise ArgumentError, "tried to flatten recursive Set"
126
+ end
127
+
128
+ seen.add(e_id)
129
+ flatten_merge(e, seen)
130
+ seen.delete(e_id)
131
+ else
132
+ add(e)
133
+ end
134
+ }
135
+
136
+ self
137
+ end
138
+ protected :flatten_merge
139
+
140
+ # Returns a new set that is a copy of the set, flattening each
141
+ # containing set recursively.
142
+ def flatten
143
+ self.class.new.flatten_merge(self)
144
+ end
145
+
146
+ # Equivalent to Set#flatten, but replaces the receiver with the
147
+ # result in place. Returns nil if no modifications were made.
148
+ def flatten!
149
+ if detect { |e| e.is_a?(Set) }
150
+ replace(flatten())
151
+ else
152
+ nil
153
+ end
154
+ end
155
+
156
+ # Returns true if the set contains the given object.
157
+ def include?(o)
158
+ @hash.include?(o)
159
+ end
160
+ alias member? include?
161
+
162
+ # Returns true if the set is a superset of the given set.
163
+ def superset?(set)
164
+ raise ArgumentError, "value must be a set" unless set.is_a?(Set)
165
+ return false if size < set.size
166
+ set.all? { |o| include?(o) }
167
+ end
168
+
169
+ # Returns true if the set is a proper superset of the given set.
170
+ def proper_superset?(set)
171
+ raise ArgumentError, "value must be a set" unless set.is_a?(Set)
172
+ return false if size <= set.size
173
+ set.all? { |o| include?(o) }
174
+ end
175
+
176
+ # Returns true if the set is a subset of the given set.
177
+ def subset?(set)
178
+ raise ArgumentError, "value must be a set" unless set.is_a?(Set)
179
+ return false if set.size < size
180
+ all? { |o| set.include?(o) }
181
+ end
182
+
183
+ # Returns true if the set is a proper subset of the given set.
184
+ def proper_subset?(set)
185
+ raise ArgumentError, "value must be a set" unless set.is_a?(Set)
186
+ return false if set.size <= size
187
+ all? { |o| set.include?(o) }
188
+ end
189
+
190
+ # Calls the given block once for each element in the set, passing
191
+ # the element as parameter. Returns an enumerator if no block is
192
+ # given.
193
+ def each
194
+ return enum_for(:each) unless block_given?
195
+ @hash.each_key { |o| yield(o) }
196
+ self
197
+ end
198
+
199
+ # Adds the given object to the set and returns self. Use +merge+ to
200
+ # add several elements at once.
201
+ def add(o)
202
+ @hash[o] = true
203
+ self
204
+ end
205
+ alias << add
206
+
207
+ # Adds the given object to the set and returns self. If the
208
+ # object is already in the set, returns nil.
209
+ def add?(o)
210
+ if include?(o)
211
+ nil
212
+ else
213
+ add(o)
214
+ end
215
+ end
216
+
217
+ # Deletes the given object from the set and returns self. Use +subtract+ to
218
+ # delete several items at once.
219
+ def delete(o)
220
+ @hash.delete(o)
221
+ self
222
+ end
223
+
224
+ # Deletes the given object from the set and returns self. If the
225
+ # object is not in the set, returns nil.
226
+ def delete?(o)
227
+ if include?(o)
228
+ delete(o)
229
+ else
230
+ nil
231
+ end
232
+ end
233
+
234
+ # Deletes every element of the set for which block evaluates to
235
+ # true, and returns self.
236
+ def delete_if
237
+ to_a.each { |o| @hash.delete(o) if yield(o) }
238
+ self
239
+ end
240
+
241
+ # Do collect() destructively.
242
+ def collect!
243
+ set = self.class.new
244
+ each { |o| set << yield(o) }
245
+ replace(set)
246
+ end
247
+ alias map! collect!
248
+
249
+ # Equivalent to Set#delete_if, but returns nil if no changes were
250
+ # made.
251
+ def reject!
252
+ n = size
253
+ delete_if { |o| yield(o) }
254
+ size == n ? nil : self
255
+ end
256
+
257
+ # Merges the elements of the given enumerable object to the set and
258
+ # returns self.
259
+ def merge(enum)
260
+ if enum.is_a?(Set)
261
+ @hash.update(enum.instance_eval { @hash })
262
+ else
263
+ raise ArgumentError, "value must be enumerable" unless enum.is_a?(Enumerable)
264
+ enum.each { |o| add(o) }
265
+ end
266
+
267
+ self
268
+ end
269
+
270
+ # Deletes every element that appears in the given enumerable object
271
+ # and returns self.
272
+ def subtract(enum)
273
+ raise ArgumentError, "value must be enumerable" unless enum.is_a?(Enumerable)
274
+ enum.each { |o| delete(o) }
275
+ self
276
+ end
277
+
278
+ # Returns a new set built by merging the set and the elements of the
279
+ # given enumerable object.
280
+ def |(enum)
281
+ raise ArgumentError, "value must be enumerable" unless enum.is_a?(Enumerable)
282
+ dup.merge(enum)
283
+ end
284
+ alias + | ##
285
+ alias union | ##
286
+
287
+ # Returns a new set built by duplicating the set, removing every
288
+ # element that appears in the given enumerable object.
289
+ def -(enum)
290
+ raise ArgumentError, "value must be enumerable" unless enum.is_a?(Enumerable)
291
+ dup.subtract(enum)
292
+ end
293
+ alias difference - ##
294
+
295
+ # Returns a new set containing elements common to the set and the
296
+ # given enumerable object.
297
+ def &(enum)
298
+ raise ArgumentError, "value must be enumerable" unless enum.is_a?(Enumerable)
299
+ n = self.class.new
300
+ enum.each { |o| n.add(o) if include?(o) }
301
+ n
302
+ end
303
+ alias intersection & ##
304
+
305
+ # Returns a new set containing elements exclusive between the set
306
+ # and the given enumerable object. (set ^ enum) is equivalent to
307
+ # ((set | enum) - (set & enum)).
308
+ def ^(enum)
309
+ raise ArgumentError, "value must be enumerable" unless enum.is_a?(Enumerable)
310
+ n = Set.new(enum)
311
+ each { |o| if n.include?(o) then n.delete(o) else n.add(o) end }
312
+ n
313
+ end
314
+
315
+ # Returns true if two sets are equal. The equality of each couple
316
+ # of elements is defined according to Object#eql?.
317
+ def ==(set)
318
+ return true if equal?(set)
319
+
320
+ return false unless set.is_a?(Set) && size == set.size
321
+
322
+ hash = @hash.dup
323
+ set.all? { |o| hash.include?(o) }
324
+ end
325
+
326
+ def hash # :nodoc:
327
+ @hash.hash
328
+ end
329
+
330
+ def eql?(o) # :nodoc:
331
+ return false unless o.is_a?(Set)
332
+ @hash.eql?(o.instance_eval{@hash})
333
+ end
334
+
335
+ # Classifies the set by the return value of the given block and
336
+ # returns a hash of {value => set of elements} pairs. The block is
337
+ # called once for each element of the set, passing the element as
338
+ # parameter.
339
+ #
340
+ # e.g.:
341
+ #
342
+ # require 'set'
343
+ # files = Set.new(Dir.glob("*.rb"))
344
+ # hash = files.classify { |f| File.mtime(f).year }
345
+ # p hash # => {2000=>#<Set: {"a.rb", "b.rb"}>,
346
+ # # 2001=>#<Set: {"c.rb", "d.rb", "e.rb"}>,
347
+ # # 2002=>#<Set: {"f.rb"}>}
348
+ def classify # :yields: o
349
+ h = {}
350
+
351
+ each { |i|
352
+ x = yield(i)
353
+ (h[x] ||= self.class.new).add(i)
354
+ }
355
+
356
+ h
357
+ end
358
+
359
+ # Divides the set into a set of subsets according to the commonality
360
+ # defined by the given block.
361
+ #
362
+ # If the arity of the block is 2, elements o1 and o2 are in common
363
+ # if block.call(o1, o2) is true. Otherwise, elements o1 and o2 are
364
+ # in common if block.call(o1) == block.call(o2).
365
+ #
366
+ # e.g.:
367
+ #
368
+ # require 'set'
369
+ # numbers = Set[1, 3, 4, 6, 9, 10, 11]
370
+ # set = numbers.divide { |i,j| (i - j).abs == 1 }
371
+ # p set # => #<Set: {#<Set: {1}>,
372
+ # # #<Set: {11, 9, 10}>,
373
+ # # #<Set: {3, 4}>,
374
+ # # #<Set: {6}>}>
375
+ def divide(&func)
376
+ if func.arity == 2
377
+ require 'tsort'
378
+
379
+ class << dig = {} # :nodoc:
380
+ include TSort
381
+
382
+ alias tsort_each_node each_key
383
+ def tsort_each_child(node, &block)
384
+ fetch(node).each(&block)
385
+ end
386
+ end
387
+
388
+ each { |u|
389
+ dig[u] = a = []
390
+ each{ |v| func.call(u, v) and a << v }
391
+ }
392
+
393
+ set = Set.new()
394
+ dig.each_strongly_connected_component { |css|
395
+ set.add(self.class.new(css))
396
+ }
397
+ set
398
+ else
399
+ Set.new(classify(&func).values)
400
+ end
401
+ end
402
+
403
+ InspectKey = :__inspect_key__ # :nodoc:
404
+
405
+ # Returns a string containing a human-readable representation of the
406
+ # set. ("#<Set: {element1, element2, ...}>")
407
+ def inspect
408
+ ids = (Thread.current[InspectKey] ||= [])
409
+
410
+ if ids.include?(object_id)
411
+ return sprintf('#<%s: {...}>', self.class.name)
412
+ end
413
+
414
+ begin
415
+ ids << object_id
416
+ return sprintf('#<%s: {%s}>', self.class, to_a.inspect[1..-2])
417
+ ensure
418
+ ids.pop
419
+ end
420
+ end
421
+
422
+ def pretty_print(pp) # :nodoc:
423
+ pp.text sprintf('#<%s: {', self.class.name)
424
+ pp.nest(1) {
425
+ pp.seplist(self) { |o|
426
+ pp.pp o
427
+ }
428
+ }
429
+ pp.text "}>"
430
+ end
431
+
432
+ def pretty_print_cycle(pp) # :nodoc:
433
+ pp.text sprintf('#<%s: {%s}>', self.class.name, empty? ? '' : '...')
434
+ end
435
+ end
436
+
437
+ # SortedSet implements a set which elements are sorted in order. See Set.
438
+ class SortedSet < Set
439
+ @@setup = false
440
+
441
+ class << self
442
+ def [](*ary) # :nodoc:
443
+ new(ary)
444
+ end
445
+ end
446
+
447
+ def initialize(*args, &block)
448
+ @keys = nil
449
+ super
450
+ end
451
+
452
+ def clear
453
+ @keys = nil
454
+ super
455
+ end
456
+
457
+ def replace(enum)
458
+ @keys = nil
459
+ super
460
+ end
461
+
462
+ def add(o)
463
+ raise ArgumentError, "value must respond to <=>" unless o.respond_to?(:<=>)
464
+ @keys = nil
465
+ @hash[o] = true
466
+ self
467
+ end
468
+
469
+ alias << add
470
+
471
+ def delete(o)
472
+ @keys = nil
473
+ @hash.delete(o)
474
+ self
475
+ end
476
+
477
+ def delete_if
478
+ n = @hash.size
479
+ super
480
+ @keys = nil if @hash.size != n
481
+ self
482
+ end
483
+
484
+ def merge(enum)
485
+ @keys = nil
486
+ super
487
+ end
488
+
489
+ def each
490
+ return enum_for(:each) unless block_given?
491
+ to_a.each { |o| yield(o) }
492
+ self
493
+ end
494
+
495
+ def to_a
496
+ unless @keys
497
+ keys = @hash.keys
498
+ keys.sort!
499
+ @keys = keys
500
+ end
501
+ @keys
502
+ end
503
+
504
+ end
505
+
506
+ module Enumerable
507
+ # Makes a set from the enumerable object with given arguments.
508
+ # Needs to +require "set"+ to use this method.
509
+ def to_set(klass = Set, *args, &block)
510
+ klass.new(self, *args, &block)
511
+ end
512
+ end
513
+
514
+ # =begin
515
+ # == RestricedSet class
516
+ # RestricedSet implements a set with restrictions defined by a given
517
+ # block.
518
+ #
519
+ # === Super class
520
+ # Set
521
+ #
522
+ # === Class Methods
523
+ # --- RestricedSet::new(enum = nil) { |o| ... }
524
+ # --- RestricedSet::new(enum = nil) { |rset, o| ... }
525
+ # Creates a new restricted set containing the elements of the given
526
+ # enumerable object. Restrictions are defined by the given block.
527
+ #
528
+ # If the block's arity is 2, it is called with the RestrictedSet
529
+ # itself and an object to see if the object is allowed to be put in
530
+ # the set.
531
+ #
532
+ # Otherwise, the block is called with an object to see if the object
533
+ # is allowed to be put in the set.
534
+ #
535
+ # === Instance Methods
536
+ # --- restriction_proc
537
+ # Returns the restriction procedure of the set.
538
+ #
539
+ # =end
540
+ #
541
+ # class RestricedSet < Set
542
+ # def initialize(*args, &block)
543
+ # @proc = block or raise ArgumentError, "missing a block"
544
+ #
545
+ # if @proc.arity == 2
546
+ # instance_eval %{
547
+ # def add(o)
548
+ # @hash[o] = true if @proc.call(self, o)
549
+ # self
550
+ # end
551
+ # alias << add
552
+ #
553
+ # def add?(o)
554
+ # if include?(o) || !@proc.call(self, o)
555
+ # nil
556
+ # else
557
+ # @hash[o] = true
558
+ # self
559
+ # end
560
+ # end
561
+ #
562
+ # def replace(enum)
563
+ # enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
564
+ # clear
565
+ # enum.each { |o| add(o) }
566
+ #
567
+ # self
568
+ # end
569
+ #
570
+ # def merge(enum)
571
+ # enum.is_a?(Enumerable) or raise ArgumentError, "value must be enumerable"
572
+ # enum.each { |o| add(o) }
573
+ #
574
+ # self
575
+ # end
576
+ # }
577
+ # else
578
+ # instance_eval %{
579
+ # def add(o)
580
+ # if @proc.call(o)
581
+ # @hash[o] = true
582
+ # end
583
+ # self
584
+ # end
585
+ # alias << add
586
+ #
587
+ # def add?(o)
588
+ # if include?(o) || !@proc.call(o)
589
+ # nil
590
+ # else
591
+ # @hash[o] = true
592
+ # self
593
+ # end
594
+ # end
595
+ # }
596
+ # end
597
+ #
598
+ # super(*args)
599
+ # end
600
+ #
601
+ # def restriction_proc
602
+ # @proc
603
+ # end
604
+ # end
605
+
606
+ # if $0 == __FILE__
607
+ # eval DATA.read, nil, $0, __LINE__+4
608
+ # end
609
+
610
+ __END__
611
+
612
+ require 'test/unit'
613
+
614
+ class TC_Set < Test::Unit::TestCase
615
+ def test_aref
616
+ assert_nothing_raised {
617
+ Set[]
618
+ Set[nil]
619
+ Set[1,2,3]
620
+ }
621
+
622
+ assert_equal(0, Set[].size)
623
+ assert_equal(1, Set[nil].size)
624
+ assert_equal(1, Set[[]].size)
625
+ assert_equal(1, Set[[nil]].size)
626
+
627
+ set = Set[2,4,6,4]
628
+ assert_equal(Set.new([2,4,6]), set)
629
+ end
630
+
631
+ def test_s_new
632
+ assert_nothing_raised {
633
+ Set.new()
634
+ Set.new(nil)
635
+ Set.new([])
636
+ Set.new([1,2])
637
+ Set.new('a'..'c')
638
+ Set.new('XYZ')
639
+ }
640
+ assert_raises(ArgumentError) {
641
+ Set.new(false)
642
+ }
643
+ assert_raises(ArgumentError) {
644
+ Set.new(1)
645
+ }
646
+ assert_raises(ArgumentError) {
647
+ Set.new(1,2)
648
+ }
649
+
650
+ assert_equal(0, Set.new().size)
651
+ assert_equal(0, Set.new(nil).size)
652
+ assert_equal(0, Set.new([]).size)
653
+ assert_equal(1, Set.new([nil]).size)
654
+
655
+ ary = [2,4,6,4]
656
+ set = Set.new(ary)
657
+ ary.clear
658
+ assert_equal(false, set.empty?)
659
+ assert_equal(3, set.size)
660
+
661
+ ary = [1,2,3]
662
+
663
+ s = Set.new(ary) { |o| o * 2 }
664
+ assert_equal([2,4,6], s.sort)
665
+ end
666
+
667
+ def test_clone
668
+ set1 = Set.new
669
+ set2 = set1.clone
670
+ set1 << 'abc'
671
+ assert_equal(Set.new, set2)
672
+ end
673
+
674
+ def test_dup
675
+ set1 = Set[1,2]
676
+ set2 = set1.dup
677
+
678
+ assert_not_same(set1, set2)
679
+
680
+ assert_equal(set1, set2)
681
+
682
+ set1.add(3)
683
+
684
+ assert_not_equal(set1, set2)
685
+ end
686
+
687
+ def test_size
688
+ assert_equal(0, Set[].size)
689
+ assert_equal(2, Set[1,2].size)
690
+ assert_equal(2, Set[1,2,1].size)
691
+ end
692
+
693
+ def test_empty?
694
+ assert_equal(true, Set[].empty?)
695
+ assert_equal(false, Set[1, 2].empty?)
696
+ end
697
+
698
+ def test_clear
699
+ set = Set[1,2]
700
+ ret = set.clear
701
+
702
+ assert_same(set, ret)
703
+ assert_equal(true, set.empty?)
704
+ end
705
+
706
+ def test_replace
707
+ set = Set[1,2]
708
+ ret = set.replace('a'..'c')
709
+
710
+ assert_same(set, ret)
711
+ assert_equal(Set['a','b','c'], set)
712
+ end
713
+
714
+ def test_to_a
715
+ set = Set[1,2,3,2]
716
+ ary = set.to_a
717
+
718
+ assert_equal([1,2,3], ary.sort)
719
+ end
720
+
721
+ def test_flatten
722
+ # test1
723
+ set1 = Set[
724
+ 1,
725
+ Set[
726
+ 5,
727
+ Set[7,
728
+ Set[0]
729
+ ],
730
+ Set[6,2],
731
+ 1
732
+ ],
733
+ 3,
734
+ Set[3,4]
735
+ ]
736
+
737
+ set2 = set1.flatten
738
+ set3 = Set.new(0..7)
739
+
740
+ assert_not_same(set2, set1)
741
+ assert_equal(set3, set2)
742
+
743
+ # test2; destructive
744
+ orig_set1 = set1
745
+ set1.flatten!
746
+
747
+ assert_same(orig_set1, set1)
748
+ assert_equal(set3, set1)
749
+
750
+ # test3; multiple occurrences of a set in an set
751
+ set1 = Set[1, 2]
752
+ set2 = Set[set1, Set[set1, 4], 3]
753
+
754
+ assert_nothing_raised {
755
+ set2.flatten!
756
+ }
757
+
758
+ assert_equal(Set.new(1..4), set2)
759
+
760
+ # test4; recursion
761
+ set2 = Set[]
762
+ set1 = Set[1, set2]
763
+ set2.add(set1)
764
+
765
+ assert_raises(ArgumentError) {
766
+ set1.flatten!
767
+ }
768
+
769
+ # test5; miscellaneous
770
+ empty = Set[]
771
+ set = Set[Set[empty, "a"],Set[empty, "b"]]
772
+
773
+ assert_nothing_raised {
774
+ set.flatten
775
+ }
776
+
777
+ set1 = empty.merge(Set["no_more", set])
778
+
779
+ assert_nil(Set.new(0..31).flatten!)
780
+
781
+ x = Set[Set[],Set[1,2]].flatten!
782
+ y = Set[1,2]
783
+
784
+ assert_equal(x, y)
785
+ end
786
+
787
+ def test_include?
788
+ set = Set[1,2,3]
789
+
790
+ assert_equal(true, set.include?(1))
791
+ assert_equal(true, set.include?(2))
792
+ assert_equal(true, set.include?(3))
793
+ assert_equal(false, set.include?(0))
794
+ assert_equal(false, set.include?(nil))
795
+
796
+ set = Set["1",nil,"2",nil,"0","1",false]
797
+ assert_equal(true, set.include?(nil))
798
+ assert_equal(true, set.include?(false))
799
+ assert_equal(true, set.include?("1"))
800
+ assert_equal(false, set.include?(0))
801
+ assert_equal(false, set.include?(true))
802
+ end
803
+
804
+ def test_superset?
805
+ set = Set[1,2,3]
806
+
807
+ assert_raises(ArgumentError) {
808
+ set.superset?()
809
+ }
810
+
811
+ assert_raises(ArgumentError) {
812
+ set.superset?(2)
813
+ }
814
+
815
+ assert_raises(ArgumentError) {
816
+ set.superset?([2])
817
+ }
818
+
819
+ assert_equal(true, set.superset?(Set[]))
820
+ assert_equal(true, set.superset?(Set[1,2]))
821
+ assert_equal(true, set.superset?(Set[1,2,3]))
822
+ assert_equal(false, set.superset?(Set[1,2,3,4]))
823
+ assert_equal(false, set.superset?(Set[1,4]))
824
+
825
+ assert_equal(true, Set[].superset?(Set[]))
826
+ end
827
+
828
+ def test_proper_superset?
829
+ set = Set[1,2,3]
830
+
831
+ assert_raises(ArgumentError) {
832
+ set.proper_superset?()
833
+ }
834
+
835
+ assert_raises(ArgumentError) {
836
+ set.proper_superset?(2)
837
+ }
838
+
839
+ assert_raises(ArgumentError) {
840
+ set.proper_superset?([2])
841
+ }
842
+
843
+ assert_equal(true, set.proper_superset?(Set[]))
844
+ assert_equal(true, set.proper_superset?(Set[1,2]))
845
+ assert_equal(false, set.proper_superset?(Set[1,2,3]))
846
+ assert_equal(false, set.proper_superset?(Set[1,2,3,4]))
847
+ assert_equal(false, set.proper_superset?(Set[1,4]))
848
+
849
+ assert_equal(false, Set[].proper_superset?(Set[]))
850
+ end
851
+
852
+ def test_subset?
853
+ set = Set[1,2,3]
854
+
855
+ assert_raises(ArgumentError) {
856
+ set.subset?()
857
+ }
858
+
859
+ assert_raises(ArgumentError) {
860
+ set.subset?(2)
861
+ }
862
+
863
+ assert_raises(ArgumentError) {
864
+ set.subset?([2])
865
+ }
866
+
867
+ assert_equal(true, set.subset?(Set[1,2,3,4]))
868
+ assert_equal(true, set.subset?(Set[1,2,3]))
869
+ assert_equal(false, set.subset?(Set[1,2]))
870
+ assert_equal(false, set.subset?(Set[]))
871
+
872
+ assert_equal(true, Set[].subset?(Set[1]))
873
+ assert_equal(true, Set[].subset?(Set[]))
874
+ end
875
+
876
+ def test_proper_subset?
877
+ set = Set[1,2,3]
878
+
879
+ assert_raises(ArgumentError) {
880
+ set.proper_subset?()
881
+ }
882
+
883
+ assert_raises(ArgumentError) {
884
+ set.proper_subset?(2)
885
+ }
886
+
887
+ assert_raises(ArgumentError) {
888
+ set.proper_subset?([2])
889
+ }
890
+
891
+ assert_equal(true, set.proper_subset?(Set[1,2,3,4]))
892
+ assert_equal(false, set.proper_subset?(Set[1,2,3]))
893
+ assert_equal(false, set.proper_subset?(Set[1,2]))
894
+ assert_equal(false, set.proper_subset?(Set[]))
895
+
896
+ assert_equal(false, Set[].proper_subset?(Set[]))
897
+ end
898
+
899
+ def test_each
900
+ ary = [1,3,5,7,10,20]
901
+ set = Set.new(ary)
902
+
903
+ ret = set.each { |o| }
904
+ assert_same(set, ret)
905
+
906
+ e = set.each
907
+ assert_instance_of(Enumerable::Enumerator, e)
908
+
909
+ assert_nothing_raised {
910
+ set.each { |o|
911
+ raise "unexpected element: #{o}" unless ary.delete(o)
912
+ }
913
+
914
+ raise "forgotten elements: #{ary.join(', ')}" unless ary.empty?
915
+ }
916
+ end
917
+
918
+ def test_add
919
+ set = Set[1,2,3]
920
+
921
+ ret = set.add(2)
922
+ assert_same(set, ret)
923
+ assert_equal(Set[1,2,3], set)
924
+
925
+ ret = set.add?(2)
926
+ assert_nil(ret)
927
+ assert_equal(Set[1,2,3], set)
928
+
929
+ ret = set.add(4)
930
+ assert_same(set, ret)
931
+ assert_equal(Set[1,2,3,4], set)
932
+
933
+ ret = set.add?(5)
934
+ assert_same(set, ret)
935
+ assert_equal(Set[1,2,3,4,5], set)
936
+ end
937
+
938
+ def test_delete
939
+ set = Set[1,2,3]
940
+
941
+ ret = set.delete(4)
942
+ assert_same(set, ret)
943
+ assert_equal(Set[1,2,3], set)
944
+
945
+ ret = set.delete?(4)
946
+ assert_nil(ret)
947
+ assert_equal(Set[1,2,3], set)
948
+
949
+ ret = set.delete(2)
950
+ assert_equal(set, ret)
951
+ assert_equal(Set[1,3], set)
952
+
953
+ ret = set.delete?(1)
954
+ assert_equal(set, ret)
955
+ assert_equal(Set[3], set)
956
+ end
957
+
958
+ def test_delete_if
959
+ set = Set.new(1..10)
960
+ ret = set.delete_if { |i| i > 10 }
961
+ assert_same(set, ret)
962
+ assert_equal(Set.new(1..10), set)
963
+
964
+ set = Set.new(1..10)
965
+ ret = set.delete_if { |i| i % 3 == 0 }
966
+ assert_same(set, ret)
967
+ assert_equal(Set[1,2,4,5,7,8,10], set)
968
+ end
969
+
970
+ def test_collect!
971
+ set = Set[1,2,3,'a','b','c',-1..1,2..4]
972
+
973
+ ret = set.collect! { |i|
974
+ case i
975
+ when Numeric
976
+ i * 2
977
+ when String
978
+ i.upcase
979
+ else
980
+ nil
981
+ end
982
+ }
983
+
984
+ assert_same(set, ret)
985
+ assert_equal(Set[2,4,6,'A','B','C',nil], set)
986
+ end
987
+
988
+ def test_reject!
989
+ set = Set.new(1..10)
990
+
991
+ ret = set.reject! { |i| i > 10 }
992
+ assert_nil(ret)
993
+ assert_equal(Set.new(1..10), set)
994
+
995
+ ret = set.reject! { |i| i % 3 == 0 }
996
+ assert_same(set, ret)
997
+ assert_equal(Set[1,2,4,5,7,8,10], set)
998
+ end
999
+
1000
+ def test_merge
1001
+ set = Set[1,2,3]
1002
+
1003
+ ret = set.merge([2,4,6])
1004
+ assert_same(set, ret)
1005
+ assert_equal(Set[1,2,3,4,6], set)
1006
+ end
1007
+
1008
+ def test_subtract
1009
+ set = Set[1,2,3]
1010
+
1011
+ ret = set.subtract([2,4,6])
1012
+ assert_same(set, ret)
1013
+ assert_equal(Set[1,3], set)
1014
+ end
1015
+
1016
+ def test_plus
1017
+ set = Set[1,2,3]
1018
+
1019
+ ret = set + [2,4,6]
1020
+ assert_not_same(set, ret)
1021
+ assert_equal(Set[1,2,3,4,6], ret)
1022
+ end
1023
+
1024
+ def test_minus
1025
+ set = Set[1,2,3]
1026
+
1027
+ ret = set - [2,4,6]
1028
+ assert_not_same(set, ret)
1029
+ assert_equal(Set[1,3], ret)
1030
+ end
1031
+
1032
+ def test_and
1033
+ set = Set[1,2,3,4]
1034
+
1035
+ ret = set & [2,4,6]
1036
+ assert_not_same(set, ret)
1037
+ assert_equal(Set[2,4], ret)
1038
+ end
1039
+
1040
+ def test_xor
1041
+ set = Set[1,2,3,4]
1042
+ ret = set ^ [2,4,5,5]
1043
+ assert_not_same(set, ret)
1044
+ assert_equal(Set[1,3,5], ret)
1045
+ end
1046
+
1047
+ def test_eq
1048
+ set1 = Set[2,3,1]
1049
+ set2 = Set[1,2,3]
1050
+
1051
+ assert_equal(set1, set1)
1052
+ assert_equal(set1, set2)
1053
+ assert_not_equal(Set[1], [1])
1054
+
1055
+ set1 = Class.new(Set)["a", "b"]
1056
+ set2 = Set["a", "b", set1]
1057
+ set1 = set1.add(set1.clone)
1058
+
1059
+ # assert_equal(set1, set2)
1060
+ # assert_equal(set2, set1)
1061
+ assert_equal(set2, set2.clone)
1062
+ assert_equal(set1.clone, set1)
1063
+
1064
+ assert_not_equal(Set[Exception.new,nil], Set[Exception.new,Exception.new], "[ruby-dev:26127]")
1065
+ end
1066
+
1067
+ # def test_hash
1068
+ # end
1069
+
1070
+ # def test_eql?
1071
+ # end
1072
+
1073
+ def test_classify
1074
+ set = Set.new(1..10)
1075
+ ret = set.classify { |i| i % 3 }
1076
+
1077
+ assert_equal(3, ret.size)
1078
+ assert_instance_of(Hash, ret)
1079
+ ret.each_value { |value| assert_instance_of(Set, value) }
1080
+ assert_equal(Set[3,6,9], ret[0])
1081
+ assert_equal(Set[1,4,7,10], ret[1])
1082
+ assert_equal(Set[2,5,8], ret[2])
1083
+ end
1084
+
1085
+ def test_divide
1086
+ set = Set.new(1..10)
1087
+ ret = set.divide { |i| i % 3 }
1088
+
1089
+ assert_equal(3, ret.size)
1090
+ n = 0
1091
+ ret.each { |s| n += s.size }
1092
+ assert_equal(set.size, n)
1093
+ assert_equal(set, ret.flatten)
1094
+
1095
+ set = Set[7,10,5,11,1,3,4,9,0]
1096
+ ret = set.divide { |a,b| (a - b).abs == 1 }
1097
+
1098
+ assert_equal(4, ret.size)
1099
+ n = 0
1100
+ ret.each { |s| n += s.size }
1101
+ assert_equal(set.size, n)
1102
+ assert_equal(set, ret.flatten)
1103
+ ret.each { |s|
1104
+ if s.include?(0)
1105
+ assert_equal(Set[0,1], s)
1106
+ elsif s.include?(3)
1107
+ assert_equal(Set[3,4,5], s)
1108
+ elsif s.include?(7)
1109
+ assert_equal(Set[7], s)
1110
+ elsif s.include?(9)
1111
+ assert_equal(Set[9,10,11], s)
1112
+ else
1113
+ raise "unexpected group: #{s.inspect}"
1114
+ end
1115
+ }
1116
+ end
1117
+
1118
+ def test_inspect
1119
+ set1 = Set[1]
1120
+
1121
+ assert_equal('#<Set: {1}>', set1.inspect)
1122
+
1123
+ set2 = Set[Set[0], 1, 2, set1]
1124
+ assert_equal(false, set2.inspect.include?('#<Set: {...}>'))
1125
+
1126
+ set1.add(set2)
1127
+ assert_equal(true, set1.inspect.include?('#<Set: {...}>'))
1128
+ end
1129
+
1130
+ # def test_pretty_print
1131
+ # end
1132
+
1133
+ # def test_pretty_print_cycle
1134
+ # end
1135
+ end
1136
+
1137
+ class TC_SortedSet < Test::Unit::TestCase
1138
+ def test_sortedset
1139
+ s = SortedSet[4,5,3,1,2]
1140
+
1141
+ assert_equal([1,2,3,4,5], s.to_a)
1142
+
1143
+ prev = nil
1144
+ s.each { |o| assert(prev < o) if prev; prev = o }
1145
+ assert_not_nil(prev)
1146
+
1147
+ s.map! { |o| -2 * o }
1148
+
1149
+ assert_equal([-10,-8,-6,-4,-2], s.to_a)
1150
+
1151
+ prev = nil
1152
+ ret = s.each { |o| assert(prev < o) if prev; prev = o }
1153
+ assert_not_nil(prev)
1154
+ assert_same(s, ret)
1155
+
1156
+ s = SortedSet.new([2,1,3]) { |o| o * -2 }
1157
+ assert_equal([-6,-4,-2], s.to_a)
1158
+
1159
+ s = SortedSet.new(['one', 'two', 'three', 'four'])
1160
+ a = []
1161
+ ret = s.delete_if { |o| a << o; o.start_with?('t') }
1162
+ assert_same(s, ret)
1163
+ assert_equal(['four', 'one'], s.to_a)
1164
+ assert_equal(['four', 'one', 'three', 'two'], a)
1165
+
1166
+ s = SortedSet.new(['one', 'two', 'three', 'four'])
1167
+ a = []
1168
+ ret = s.reject! { |o| a << o; o.start_with?('t') }
1169
+ assert_same(s, ret)
1170
+ assert_equal(['four', 'one'], s.to_a)
1171
+ assert_equal(['four', 'one', 'three', 'two'], a)
1172
+
1173
+ s = SortedSet.new(['one', 'two', 'three', 'four'])
1174
+ a = []
1175
+ ret = s.reject! { |o| a << o; false }
1176
+ assert_same(nil, ret)
1177
+ assert_equal(['four', 'one', 'three', 'two'], s.to_a)
1178
+ assert_equal(['four', 'one', 'three', 'two'], a)
1179
+ end
1180
+ end
1181
+
1182
+ class TC_Enumerable < Test::Unit::TestCase
1183
+ def test_to_set
1184
+ ary = [2,5,4,3,2,1,3]
1185
+
1186
+ set = ary.to_set
1187
+ assert_instance_of(Set, set)
1188
+ assert_equal([1,2,3,4,5], set.sort)
1189
+
1190
+ set = ary.to_set { |o| o * -2 }
1191
+ assert_instance_of(Set, set)
1192
+ assert_equal([-10,-8,-6,-4,-2], set.sort)
1193
+
1194
+ set = ary.to_set(SortedSet)
1195
+ assert_instance_of(SortedSet, set)
1196
+ assert_equal([1,2,3,4,5], set.to_a)
1197
+
1198
+ set = ary.to_set(SortedSet) { |o| o * -2 }
1199
+ assert_instance_of(SortedSet, set)
1200
+ assert_equal([-10,-8,-6,-4,-2], set.sort)
1201
+ end
1202
+ end
1203
+
1204
+ # class TC_RestricedSet < Test::Unit::TestCase
1205
+ # def test_s_new
1206
+ # assert_raises(ArgumentError) { RestricedSet.new }
1207
+ #
1208
+ # s = RestricedSet.new([-1,2,3]) { |o| o > 0 }
1209
+ # assert_equal([2,3], s.sort)
1210
+ # end
1211
+ #
1212
+ # def test_restriction_proc
1213
+ # s = RestricedSet.new([-1,2,3]) { |o| o > 0 }
1214
+ #
1215
+ # f = s.restriction_proc
1216
+ # assert_instance_of(Proc, f)
1217
+ # assert(f[1])
1218
+ # assert(!f[0])
1219
+ # end
1220
+ #
1221
+ # def test_replace
1222
+ # s = RestricedSet.new(-3..3) { |o| o > 0 }
1223
+ # assert_equal([1,2,3], s.sort)
1224
+ #
1225
+ # s.replace([-2,0,3,4,5])
1226
+ # assert_equal([3,4,5], s.sort)
1227
+ # end
1228
+ #
1229
+ # def test_merge
1230
+ # s = RestricedSet.new { |o| o > 0 }
1231
+ # s.merge(-5..5)
1232
+ # assert_equal([1,2,3,4,5], s.sort)
1233
+ #
1234
+ # s.merge([10,-10,-8,8])
1235
+ # assert_equal([1,2,3,4,5,8,10], s.sort)
1236
+ # end
1237
+ # end