stakach-algorithms 1.0.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.
@@ -0,0 +1,273 @@
1
+ require 'containers/stack'
2
+ =begin rdoc
3
+ A SplayTreeMap is a map that is stored in ascending order of its keys, determined by applying
4
+ the function <=> to compare keys. No duplicate values for keys are allowed, so new values of a key
5
+ overwrites the old value of the key.
6
+
7
+ A major advantage of SplayTreeMap over a Hash is the fact that keys are stored in order and can thus be
8
+ iterated over in order. Also, Splay Trees are self-optimizing as recently accessed nodes stay near
9
+ the root and are easily re-accessed later. Splay Trees are also more simply implemented than Red-Black
10
+ trees.
11
+
12
+ Splay trees have amortized O(log n) performance for most methods, but are O(n) worst case. This happens
13
+ when keys are added in sorted order, causing the tree to have a height of the number of items added.
14
+
15
+ =end
16
+ module Algorithms
17
+ module Containers
18
+ class RubySplayTreeMap
19
+ include Enumerable
20
+
21
+ Node = Struct.new(:key, :value, :left, :right)
22
+
23
+ # Create and initialize a new empty SplayTreeMap.
24
+ def initialize
25
+ @size = 0
26
+ clear
27
+ end
28
+
29
+ # Insert an item with an associated key into the SplayTreeMap, and returns the item inserted
30
+ #
31
+ # Complexity: amortized O(log n)
32
+ #
33
+ # map = Algorithms::Containers::SplayTreeMap.new
34
+ # map.push("MA", "Massachusetts") #=> "Massachusetts"
35
+ # map.get("MA") #=> "Massachusetts"
36
+ def push(key, value)
37
+ if @root.nil?
38
+ @root = Node.new(key, value, nil, nil)
39
+ @size = 1
40
+ return value
41
+ end
42
+ splay(key)
43
+
44
+ cmp = (key <=> @root.key)
45
+ if cmp == 0
46
+ @root.value = value
47
+ return value
48
+ end
49
+ node = Node.new(key, value, nil, nil)
50
+ if cmp < 1
51
+ node.left = @root.left
52
+ node.right = @root
53
+ @root.left = nil
54
+ else
55
+ node.right = @root.right
56
+ node.left = @root
57
+ @root.right = nil
58
+ end
59
+ @root = node
60
+ @size += 1
61
+ value
62
+ end
63
+ alias_method :[]=, :push
64
+
65
+ # Return the number of items in the SplayTreeMap.
66
+ #
67
+ # map = Algorithms::Containers::SplayTreeMap.new
68
+ # map.push("MA", "Massachusetts")
69
+ # map.push("GA", "Georgia")
70
+ # map.size #=> 2
71
+ def size
72
+ @size
73
+ end
74
+
75
+ # Remove all elements from the SplayTreeMap
76
+ #
77
+ # Complexity: O(1)
78
+ #
79
+ def clear
80
+ @root = nil
81
+ @size = 0
82
+ @header = Node.new(nil, nil, nil, nil)
83
+ end
84
+
85
+ # Return the height of the tree structure in the SplayTreeMap.
86
+ #
87
+ # Complexity: O(log n)
88
+ #
89
+ # map = Algorithms::Containers::SplayTreeMap.new
90
+ # map.push("MA", "Massachusetts")
91
+ # map.push("GA", "Georgia")
92
+ # map.height #=> 2
93
+ def height
94
+ height_recursive(@root)
95
+ end
96
+
97
+ # Return true if key is found in the SplayTreeMap, false otherwise.
98
+ #
99
+ # Complexity: amortized O(log n)
100
+ #
101
+ # map = Algorithms::Containers::SplayTreeMap.new
102
+ # map["MA"] = "Massachusetts"
103
+ # map["GA"] = "Georgia"
104
+ # map.has_key?("GA") #=> true
105
+ # map.has_key?("DE") #=> false
106
+ def has_key?(key)
107
+ !get(key).nil?
108
+ end
109
+
110
+ # Return the item associated with the key, or nil if none found.
111
+ #
112
+ # Complexity: amortized O(log n)
113
+ #
114
+ # map = Algorithms::Containers::SplayTreeMap.new
115
+ # map.push("MA", "Massachusetts")
116
+ # map.push("GA", "Georgia")
117
+ # map.get("GA") #=> "Georgia"
118
+ def get(key)
119
+ return nil if @root.nil?
120
+
121
+ splay(key)
122
+ (@root.key <=> key) == 0 ? @root.value : nil
123
+ end
124
+ alias_method :[], :get
125
+
126
+ # Return the smallest [key, value] pair in the SplayTreeMap, or nil if the tree is empty.
127
+ #
128
+ # Complexity: amortized O(log n)
129
+ #
130
+ # map = Algorithms::Containers::SplayTreeMap.new
131
+ # map["MA"] = "Massachusetts"
132
+ # map["GA"] = "Georgia"
133
+ # map.min #=> ["GA", "Georgia"]
134
+ def min
135
+ return nil if @root.nil?
136
+ n = @root
137
+ while n.left
138
+ n = n.left
139
+ end
140
+ splay(n.key)
141
+ return [n.key, n.value]
142
+ end
143
+
144
+ # Return the largest [key, value] pair in the SplayTreeMap, or nil if the tree is empty.
145
+ #
146
+ # Complexity: amortized O(log n)
147
+ #
148
+ # map = Algorithms::Containers::SplayTreeMap.new
149
+ # map["MA"] = "Massachusetts"
150
+ # map["GA"] = "Georgia"
151
+ # map.max #=> ["MA", "Massachusetts"]
152
+ def max
153
+ return nil if @root.nil?
154
+ n = @root
155
+ while n.right
156
+ n = n.right
157
+ end
158
+ splay(n.key)
159
+ return [n.key, n.value]
160
+ end
161
+
162
+ # Deletes the item and key if it's found, and returns the item. Returns nil
163
+ # if key is not present.
164
+ #
165
+ # Complexity: amortized O(log n)
166
+ #
167
+ # map = Algorithms::Containers::SplayTreeMap.new
168
+ # map["MA"] = "Massachusetts"
169
+ # map["GA"] = "Georgia"
170
+ # map.delete("GA") #=> "Georgia"
171
+ # map.delete("DE") #=> nil
172
+ def delete(key)
173
+ return nil if @root.nil?
174
+ deleted = nil
175
+ splay(key)
176
+ if (key <=> @root.key) == 0 # The key exists
177
+ deleted = @root.value
178
+ if @root.left.nil?
179
+ @root = @root.right
180
+ else
181
+ x = @root.right
182
+ @root = @root.left
183
+ splay(key)
184
+ @root.right = x
185
+ end
186
+ end
187
+ deleted
188
+ end
189
+
190
+ # Iterates over the SplayTreeMap in ascending order. Uses an iterative, not recursive, approach.
191
+ def each
192
+ return nil unless @root
193
+ stack = Stack.new
194
+ cursor = @root
195
+ loop do
196
+ if cursor
197
+ stack.push(cursor)
198
+ cursor = cursor.left
199
+ else
200
+ unless stack.empty?
201
+ cursor = stack.pop
202
+ yield(cursor.key, cursor.value)
203
+ cursor = cursor.right
204
+ else
205
+ break
206
+ end
207
+ end
208
+ end
209
+ end
210
+
211
+ # Moves a key to the root, updating the structure in each step.
212
+ def splay(key)
213
+ l, r = @header, @header
214
+ t = @root
215
+ @header.left, @header.right = nil, nil
216
+
217
+ loop do
218
+ if (key <=> t.key) == -1
219
+ break unless t.left
220
+ if (key <=> t.left.key) == -1
221
+ y = t.left
222
+ t.left = y.right
223
+ y.right = t
224
+ t = y
225
+ break unless t.left
226
+ end
227
+ r.left = t
228
+ r = t
229
+ t = t.left
230
+ elsif (key <=> t.key) == 1
231
+ break unless t.right
232
+ if (key <=> t.right.key) == 1
233
+ y = t.right
234
+ t.right = y.left
235
+ y.left = t
236
+ t = y
237
+ break unless t.right
238
+ end
239
+ l.right = t
240
+ l = t
241
+ t = t.right
242
+ else
243
+ break
244
+ end
245
+ end
246
+ l.right = t.left
247
+ r.left = t.right
248
+ t.left = @header.right
249
+ t.right = @header.left
250
+ @root = t
251
+ end
252
+ private :splay
253
+
254
+ # Recursively determine height
255
+ def height_recursive(node)
256
+ return 0 if node.nil?
257
+
258
+ left_height = 1 + height_recursive(node.left)
259
+ right_height = 1 + height_recursive(node.right)
260
+
261
+ left_height > right_height ? left_height : right_height
262
+ end
263
+ private :height_recursive
264
+ end
265
+ end
266
+
267
+ begin
268
+ require 'CSplayTreeMap'
269
+ Containers::SplayTreeMap = Containers::CSplayTreeMap
270
+ rescue LoadError # C Version could not be found, try ruby version
271
+ Containers::SplayTreeMap = Containers::RubySplayTreeMap
272
+ end
273
+ end
@@ -0,0 +1,71 @@
1
+ require 'containers/deque'
2
+ =begin rdoc
3
+ A Stack is a container that keeps elements in a last-in first-out (LIFO) order. There are many
4
+ uses for stacks, including prefix-infix-postfix conversion and backtracking problems.
5
+
6
+ This implementation uses a doubly-linked list, guaranteeing O(1) complexity for all operations.
7
+
8
+ =end
9
+ module Algorithms
10
+ module Containers
11
+ class Stack
12
+ include Enumerable
13
+ # Create a new stack. Takes an optional array argument to initialize the stack.
14
+ #
15
+ # s = Algorithms::Containers::Stack.new([1, 2, 3])
16
+ # s.pop #=> 3
17
+ # s.pop #=> 2
18
+ def initialize(ary=[])
19
+ @container = Deque.new(ary)
20
+ end
21
+
22
+ # Returns the next item from the stack but does not remove it.
23
+ #
24
+ # s = Algorithms::Containers::Stack.new([1, 2, 3])
25
+ # s.next #=> 3
26
+ # s.size #=> 3
27
+ def next
28
+ @container.back
29
+ end
30
+
31
+ # Adds an item to the stack.
32
+ #
33
+ # s = Algorithms::Containers::Stack.new([1])
34
+ # s.push(2)
35
+ # s.pop #=> 2
36
+ # s.pop #=> 1
37
+ def push(obj)
38
+ @container.push_back(obj)
39
+ end
40
+ alias_method :<<, :push
41
+
42
+ # Removes the next item from the stack and returns it.
43
+ #
44
+ # s = Algorithms::Containers::Stack.new([1, 2, 3])
45
+ # s.pop #=> 3
46
+ # s.size #=> 2
47
+ def pop
48
+ @container.pop_back
49
+ end
50
+
51
+ # Return the number of items in the stack.
52
+ #
53
+ # s = Algorithms::Containers::Stack.new([1, 2, 3])
54
+ # s.size #=> 3
55
+ def size
56
+ @container.size
57
+ end
58
+
59
+ # Returns true if the stack is empty, false otherwise.
60
+ def empty?
61
+ @container.empty?
62
+ end
63
+
64
+ # Iterate over the Stack in LIFO order.
65
+ def each(&block)
66
+ @container.each_backward(&block)
67
+ end
68
+
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,72 @@
1
+ =begin rdoc
2
+ A suffix array enables fast substring search of a given string. An array of all possible substrings
3
+ is constructed and stored, and a binary search is then done to find a desired substring among those
4
+ stored. While more storage (and thus memory) is needed to create the SuffixArray, the advantage is
5
+ that substrings can be found in O(m log n) time, where m is the length of the substring to search for
6
+ and n is the total number of substrings.
7
+
8
+ =end
9
+ module Algorithms
10
+ module Containers
11
+ class SuffixArray
12
+ # Creates a new SuffixArray with a given string. Object of any class implementing a #to_s method can
13
+ # be passed in, such as integers.
14
+ #
15
+ # Complexity: O(n^2 log n)
16
+ #
17
+ # s_array = Algorithms::Containers::SuffixArray.new("abracadabra")
18
+ # s_array["abra"] #=> true
19
+ #
20
+ # number = Algorithms::Containers::SuffixArray.new(1234567)
21
+ # number[1] #=> true
22
+ # number[13] #=> false
23
+ def initialize(string)
24
+ string = string.to_s
25
+ raise ArgumentError, "SuffixArray needs to be initialized with a non-empty string" if string.empty?
26
+ @original_string = string
27
+ @suffixes = []
28
+ string.length.times do |i|
29
+ @suffixes << string[i..-1]
30
+ end
31
+
32
+ # Sort the suffixes in ascending order
33
+ @suffixes.sort! { |x, y| x <=> y }
34
+ end
35
+
36
+ # Returns true if the substring occurs in the string, false otherwise.
37
+ #
38
+ # Complexity: O(m + log n)
39
+ #
40
+ # s_array = Algorithms::Containers::SuffixArray.new("abracadabra")
41
+ # s_array.has_substring?("a") #=> true
42
+ # s_array.has_substring?("abra") #=> true
43
+ # s_array.has_substring?("abracadabra") #=> true
44
+ # s_array.has_substring?("acadabra") #=> true
45
+ # s_array.has_substring?("adabra") #=> true
46
+ # s_array.has_substring?("bra") #=> true
47
+ # s_array.has_substring?("bracadabra") #=> true
48
+ # s_array.has_substring?("cadabra") #=> true
49
+ # s_array.has_substring?("dabra") #=> true
50
+ # s_array.has_substring?("ra") #=> true
51
+ # s_array.has_substring?("racadabra") #=> true
52
+ # s_array.has_substring?("nope") #=> false
53
+ def has_substring?(substring)
54
+ substring = substring.to_s
55
+ return false if substring.empty?
56
+ substring_length = substring.length-1
57
+ l, r = 0, @suffixes.size-1
58
+ while(l <= r)
59
+ mid = (l + r) / 2
60
+ suffix = @suffixes[mid][0..substring_length]
61
+ case substring <=> suffix
62
+ when 0 then return true
63
+ when 1 then l = mid + 1
64
+ when -1 then r = mid - 1
65
+ end
66
+ end
67
+ return false
68
+ end
69
+ alias_method :[], :has_substring?
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,188 @@
1
+ =begin rdoc
2
+ A Trie is a data structure that stores key value pairs in a tree-like fashion. It allows
3
+ O(m) lookup speed, where m is the length of the key searched, and has no chance of collisions,
4
+ unlike hash tables. Because of its nature, search misses are quickly detected.
5
+
6
+ Tries are often used for longest prefix algorithms, wildcard matching, and can be used to
7
+ implement a radix sort.
8
+
9
+ This implemention is based on a Ternary Search Tree.
10
+ =end
11
+ module Algorithms
12
+ module Containers
13
+ class Trie
14
+ # Create a new, empty Trie.
15
+ #
16
+ # t =
17
+ # Trie.new
18
+ # t["hello"] = "world"
19
+ # t["hello] #=> "world"
20
+ def initialize
21
+ @root = nil
22
+ end
23
+
24
+ # Adds a key, value pair to the Trie, and returns the value if successful. The to_s method is
25
+ # called on the parameter to turn it into a string.
26
+ #
27
+ # Complexity: O(m)
28
+ #
29
+ # t = Algorithms::Containers::Trie.new
30
+ # t["hello"] = "world"
31
+ # t.push("hello", "world") # does the same thing
32
+ # t["hello"] #=> "world"
33
+ # t[1] = 1
34
+ # t[1] #=> 1
35
+ def push(key, value)
36
+ key = key.to_s
37
+ return nil if key.empty?
38
+ @root = push_recursive(@root, key, 0, value)
39
+ value
40
+ end
41
+ alias_method :[]=, :push
42
+
43
+ # Returns true if the key is contained in the Trie.
44
+ #
45
+ # Complexity: O(m) worst case
46
+ #
47
+ def has_key?(key)
48
+ key = key.to_s
49
+ return false if key.empty?
50
+ !(get_recursive(@root, key, 0).nil?)
51
+ end
52
+ alias_method :include?, :has_key?
53
+
54
+ # Returns the value of the desired key, or nil if the key doesn't exist.
55
+ #
56
+ # Complexity: O(m) worst case
57
+ #
58
+ # t = Algorithms::Containers::Trie.new
59
+ # t.get("hello") = "world"
60
+ # t.get("non-existant") #=> nil
61
+ def get(key)
62
+ key = key.to_s
63
+ return nil if key.empty?
64
+ node = get_recursive(@root, key, 0)
65
+ node ? node.last : nil
66
+ end
67
+ alias_method :[], :get
68
+
69
+ # Returns the longest key that has a prefix in common with the parameter string. If
70
+ # no match is found, the blank string "" is returned.
71
+ #
72
+ # Complexity: O(m) worst case
73
+ #
74
+ # t = Algorithms::Containers::Trie.new
75
+ # t.push("Hello", "World")
76
+ # t.push("Hello, brother", "World")
77
+ # t.push("Hello, bob", "World")
78
+ # t.longest_prefix("Hello, brandon") #=> "Hello"
79
+ # t.longest_prefix("Hel") #=> ""
80
+ # t.longest_prefix("Hello") #=> "Hello"
81
+ def longest_prefix(string)
82
+ string = string.to_s
83
+ return nil if string.empty?
84
+ len = prefix_recursive(@root, string, 0)
85
+ string[0...len]
86
+ end
87
+
88
+ # Returns a sorted array containing strings that match the parameter string. The wildcard
89
+ # characters that match any character are '*' and '.' If no match is found, an empty
90
+ # array is returned.
91
+ #
92
+ # Complexity: O(n) worst case
93
+ #
94
+ # t = Algorithms::Containers::Trie.new
95
+ # t.push("Hello", "World")
96
+ # t.push("Hilly", "World")
97
+ # t.push("Hello, bob", "World")
98
+ # t.wildcard("H*ll.") #=> ["Hello", "Hilly"]
99
+ # t.wildcard("Hel") #=> []
100
+ def wildcard(string)
101
+ string = string.to_s
102
+ return nil if string.empty?
103
+ ary = []
104
+ ary << wildcard_recursive(@root, string, 0, "")
105
+ ary.flatten.compact.sort
106
+ end
107
+
108
+ class Node # :nodoc: all
109
+ attr_accessor :left, :mid, :right, :char, :value, :end
110
+
111
+ def initialize(char, value)
112
+ @char = char
113
+ @value = value
114
+ @left = @mid = @right = nil
115
+ @end = false
116
+ end
117
+
118
+ def last?
119
+ @end == true
120
+ end
121
+ end
122
+
123
+ def wildcard_recursive(node, string, index, prefix)
124
+ return nil if node.nil? || index == string.length
125
+ arr = []
126
+ char = string[index]
127
+ if (char.chr == "*" || char.chr == "." || char < node.char)
128
+ arr << wildcard_recursive(node.left, string, index, prefix)
129
+ end
130
+ if (char.chr == "*" || char.chr == "." || char > node.char)
131
+ arr << wildcard_recursive(node.right, string, index, prefix)
132
+ end
133
+ if (char.chr == "*" || char.chr == "." || char == node.char)
134
+ arr << "#{prefix}#{node.char.chr}" if node.last?
135
+ arr << wildcard_recursive(node.mid, string, index+1, prefix + node.char.chr)
136
+ end
137
+ arr
138
+ end
139
+
140
+ def prefix_recursive(node, string, index)
141
+ return 0 if node.nil? || index == string.length
142
+ len = 0
143
+ rec_len = 0
144
+ char = string[index]
145
+ if (char < node.char)
146
+ rec_len = prefix_recursive(node.left, string, index)
147
+ elsif (char > node.char)
148
+ rec_len = prefix_recursive(node.right, string, index)
149
+ else
150
+ len = index+1 if node.last?
151
+ rec_len = prefix_recursive(node.mid, string, index+1)
152
+ end
153
+ len > rec_len ? len : rec_len
154
+ end
155
+
156
+ def push_recursive(node, string, index, value)
157
+ char = string[index]
158
+ node = Node.new(char, value) if node.nil?
159
+ if (char < node.char)
160
+ node.left = push_recursive(node.left, string, index, value)
161
+ elsif (char > node.char)
162
+ node.right = push_recursive(node.right, string, index, value)
163
+ elsif (index < string.length-1) # We're not at the end of the input string; add next char
164
+ node.mid = push_recursive(node.mid, string, index+1, value)
165
+ else
166
+ node.end = true
167
+ node.value = value
168
+ end
169
+ node
170
+ end
171
+
172
+ # Returns [char, value] if found
173
+ def get_recursive(node, string, index)
174
+ return nil if node.nil?
175
+ char = string[index]
176
+ if (char < node.char)
177
+ return get_recursive(node.left, string, index)
178
+ elsif (char > node.char)
179
+ return get_recursive(node.right, string, index)
180
+ elsif (index < string.length-1) # We're not at the end of the input string; add next char
181
+ return get_recursive(node.mid, string, index+1)
182
+ else
183
+ return node.last? ? [node.char, node.value] : nil
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stakach-algorithms
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Kanwei Li
9
+ - Stephen von Takach
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-02-01 00:00:00.000000000Z
14
+ dependencies: []
15
+ description: A library of algorithms and containers.
16
+ email:
17
+ - kanwei@gmail.com
18
+ - steve@advancedcontrol.com.au
19
+ executables: []
20
+ extensions:
21
+ - ext/containers/deque/extconf.rb
22
+ - ext/containers/rbtree_map/extconf.rb
23
+ - ext/containers/splaytree_map/extconf.rb
24
+ extra_rdoc_files:
25
+ - ext/containers/deque/deque.c
26
+ - ext/containers/deque/extconf.rb
27
+ - ext/containers/rbtree_map/extconf.rb
28
+ - ext/containers/rbtree_map/rbtree.c
29
+ - ext/containers/splaytree_map/extconf.rb
30
+ - ext/containers/splaytree_map/splaytree.c
31
+ - lib/algorithms/search.rb
32
+ - lib/algorithms/sort.rb
33
+ - lib/algorithms.rb
34
+ - lib/containers/deque.rb
35
+ - lib/containers/heap.rb
36
+ - lib/containers/kd_tree.rb
37
+ - lib/containers/priority_queue.rb
38
+ - lib/containers/queue.rb
39
+ - lib/containers/rb_tree_map.rb
40
+ - lib/containers/splay_tree_map.rb
41
+ - lib/containers/stack.rb
42
+ - lib/containers/suffix_array.rb
43
+ - lib/containers/trie.rb
44
+ - README.markdown
45
+ files:
46
+ - lib/algorithms/search.rb
47
+ - lib/algorithms/sort.rb
48
+ - lib/algorithms/string.rb
49
+ - lib/algorithms/version.rb
50
+ - lib/algorithms.rb
51
+ - lib/containers/deque.rb
52
+ - lib/containers/heap.rb
53
+ - lib/containers/kd_tree.rb
54
+ - lib/containers/priority_queue.rb
55
+ - lib/containers/queue.rb
56
+ - lib/containers/rb_tree_map.rb
57
+ - lib/containers/splay_tree_map.rb
58
+ - lib/containers/stack.rb
59
+ - lib/containers/suffix_array.rb
60
+ - lib/containers/trie.rb
61
+ - Rakefile
62
+ - README.markdown
63
+ - ext/containers/deque/deque.c
64
+ - ext/containers/deque/extconf.rb
65
+ - ext/containers/rbtree_map/extconf.rb
66
+ - ext/containers/rbtree_map/rbtree.c
67
+ - ext/containers/splaytree_map/extconf.rb
68
+ - ext/containers/splaytree_map/splaytree.c
69
+ homepage: https://github.com/stakach/algorithms
70
+ licenses: []
71
+ post_install_message:
72
+ rdoc_options:
73
+ - --line-numbers
74
+ - --inline-source
75
+ - --title
76
+ - Algorithms
77
+ - --main
78
+ - README.markdown
79
+ require_paths:
80
+ - lib
81
+ - ext
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ requirements: []
95
+ rubyforge_project:
96
+ rubygems_version: 1.8.15
97
+ signing_key:
98
+ specification_version: 3
99
+ summary: A library of algorithms and containers.
100
+ test_files: []