linked_list 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.
data/Benchmarks.txt ADDED
@@ -0,0 +1,26 @@
1
+ (in /Users/francois/Documents/work/linked_list)
2
+ Loaded suite -e
3
+ Started
4
+ .................................................................................................
5
+ Finished in 0.015711 seconds.
6
+
7
+ 97 tests, 97 assertions, 0 failures, 0 errors
8
+ Building a list of 1 million random strings
9
+ Took 4.389 seconds
10
+ Converting to an array
11
+ Took 1.686 seconds
12
+ user system total real
13
+ list#push/pop 0.350000 0.000000 0.350000 ( 0.364001)
14
+ array#push/pop 0.000000 0.000000 0.000000 ( 0.009894)
15
+ user system total real
16
+ list#last 0.000000 0.000000 0.000000 ( 0.000027)
17
+ array#last 0.000000 0.000000 0.000000 ( 0.000012)
18
+ user system total real
19
+ list#first 0.010000 0.000000 0.010000 ( 0.001188)
20
+ array#first 0.000000 0.000000 0.000000 ( 0.000449)
21
+ user system total real
22
+ list#reverse 7.540000 0.170000 7.710000 ( 7.806306)
23
+ array#reverse 0.010000 0.010000 0.020000 ( 0.008443)
24
+ user system total real
25
+ list#dup 23.080000 0.380000 23.460000 ( 24.039316)
26
+ array#dup 0.000000 0.000000 0.000000 ( 0.000017)
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 1.0.0 2008-11-12
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/Manifest.txt ADDED
@@ -0,0 +1,14 @@
1
+ History.txt
2
+ Manifest.txt
3
+ Benchmarks.txt
4
+ README.rdoc
5
+ Rakefile
6
+ lib/linked_list.rb
7
+ lib/linked_list/node.rb
8
+ script/console
9
+ script/destroy
10
+ script/generate
11
+ tasks/benchmark.rake
12
+ test/test_helper.rb
13
+ test/test_linked_list.rb
14
+ test/test_linked_list_node.rb
data/README.rdoc ADDED
@@ -0,0 +1,58 @@
1
+ = LinkedList
2
+
3
+ * http://linkedlist.rubyforge.org/
4
+
5
+ == DESCRIPTION:
6
+
7
+ A simple linked list implementation that follows Ruby's conventions.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * FIXME: #dup is implemented by reversing the list twice. This should be pretty slow... Untested, not benchmarked.
12
+ * This implementation isn't thread safe.
13
+
14
+ == SYNOPSIS:
15
+
16
+ list = LinkedList.new
17
+ list << "a"
18
+ list.push "b"
19
+ list.unshift "c"
20
+ list.inspect
21
+ #=> ("c" ("b" ("a" nil)))
22
+ list.pop
23
+ #=> ("b" ("a" nil))
24
+ list.map {|v| v*2}
25
+ #=> ("bb" ("aa" nil))
26
+
27
+ == REQUIREMENTS:
28
+
29
+ * Ruby 1.8.6+
30
+
31
+ == INSTALL:
32
+
33
+ * sudo gem install linked_list
34
+
35
+ == LICENSE:
36
+
37
+ (The MIT License)
38
+
39
+ Copyright (c) 2008 François Beausoleil
40
+
41
+ Permission is hereby granted, free of charge, to any person obtaining
42
+ a copy of this software and associated documentation files (the
43
+ 'Software'), to deal in the Software without restriction, including
44
+ without limitation the rights to use, copy, modify, merge, publish,
45
+ distribute, sublicense, and/or sell copies of the Software, and to
46
+ permit persons to whom the Software is furnished to do so, subject to
47
+ the following conditions:
48
+
49
+ The above copyright notice and this permission notice shall be
50
+ included in all copies or substantial portions of the Software.
51
+
52
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
53
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
54
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
55
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
56
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
57
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
58
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/linked_list'
3
+
4
+ # Generate all the Rake tasks
5
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
+ $hoe = Hoe.new('linked_list', LinkedList::VERSION) do |p|
7
+ p.developer('François Beausoleil', 'francois@teksol.info')
8
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
+ p.rubyforge_name = "linkedlist"
10
+ p.extra_dev_deps = [
11
+ ['newgem', ">= #{::Newgem::VERSION}"],
12
+ ['francois-shoulda', ">= 2.0.5"]
13
+ ]
14
+
15
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
16
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
17
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
18
+ p.rsync_args = '-av --delete --ignore-errors'
19
+ end
20
+
21
+ require 'newgem/tasks' # load /tasks/*.rake
22
+ Dir['tasks/**/*.rake'].each { |t| load t }
@@ -0,0 +1,204 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require "linked_list/node"
5
+
6
+ # Linked list implementation.
7
+ # Linked lists have O(1) insertions and pops. Traversal is O(n).
8
+ #
9
+ # == Implementation Notes
10
+ # This implementation isn't thread safe. In fact, traversal is thread safe, but insertions and removals aren't.
11
+ #
12
+ # This implementation has problems with #dup, but beyond that, it looks fine. It needs to be battle tested though.
13
+ # As a performance optimization, #size is cached and maintained locally, instead of being recalculated everytime.
14
+ class LinkedList
15
+ VERSION = '1.0.0'
16
+ include Enumerable
17
+
18
+ attr_reader :cdr, :size
19
+ alias_method :length, :size
20
+
21
+ def initialize
22
+ clear
23
+ end
24
+
25
+ # Two lists are equal if they have the same values in the same positions.
26
+ def ==(other)
27
+ cdr == other.cdr
28
+ end
29
+
30
+ # A list is empty if it doesn't have any nodes.
31
+ def empty?
32
+ cdr.nil?
33
+ end
34
+
35
+ # Returns a duplicate of this list, where the nodes are also copied.
36
+ # FIXME: Performance hog... The implementation sucks big time.
37
+ def dup
38
+ reverse.reverse
39
+ end
40
+
41
+ # Yields each value
42
+ def each
43
+ each_node do |node|
44
+ yield node.value
45
+ end
46
+ end
47
+
48
+ # Yields each LinkedList::Node (or subclass)
49
+ def each_node
50
+ node = cdr
51
+ while node
52
+ yield node
53
+ node = node.cdr
54
+ end
55
+ end
56
+ protected :each_node
57
+
58
+ # Returns an Array that has the same values as this LinkedList
59
+ def to_a
60
+ inject(Array.new) do |memo, value|
61
+ memo << value
62
+ end
63
+ end
64
+
65
+ def at(index)
66
+ index = normalize_index(index)
67
+ each_with_index do |value, idx|
68
+ return value if index == idx
69
+ end
70
+ nil
71
+ end
72
+
73
+ def normalize_index(index)
74
+ index < 0 ? (length + index) : index
75
+ end
76
+ protected :normalize_index
77
+
78
+ def [](*args)
79
+ case args.length
80
+ when 1
81
+ case args.first
82
+ when Range
83
+ indexes = args.first
84
+ start, stop = normalize_index(indexes.first), normalize_index(indexes.exclude_end? ? indexes.last - 1 : indexes.last)
85
+ indexes = (start .. stop)
86
+ result = []
87
+ each_with_index do |value, idx|
88
+ next unless indexes.include?(idx)
89
+ result << value
90
+ end
91
+ result
92
+ else
93
+ at(args.first)
94
+ end
95
+ when 2
96
+ index = normalize_index(args.first)
97
+ return nil unless (0 .. length).include?(index)
98
+ count = args.last
99
+ self[index ... (index + count)]
100
+ else
101
+ raise ArgumentError, "Expected (index), (index, length) or (index0..index1), received #{args.inspect}"
102
+ end
103
+ end
104
+
105
+ # Returns a new instance of self with a reverse insertion order
106
+ def reverse
107
+ list = new_species
108
+ each do |value|
109
+ list << value
110
+ end
111
+ list
112
+ end
113
+
114
+ # Destructively maps this list's values to the return value of the block
115
+ def map!
116
+ each_node do |node|
117
+ node.value = yield(node.value)
118
+ end
119
+ end
120
+
121
+ # Returns a new instance of self where the values have been replaced with the results of the block's
122
+ def map(&block)
123
+ list = dup
124
+ list.map!(&block)
125
+ list
126
+ end
127
+
128
+ # Pushes a new value at the head of this list
129
+ def <<(value)
130
+ @cdr = new_node(value, cdr)
131
+ @lcdr = @cdr if @lcdr.nil?
132
+ @size += 1
133
+ self
134
+ end
135
+ alias_method :push, :<<
136
+ alias_method :unshift, :<<
137
+
138
+ # Pops the head of the list, returning the value
139
+ def pop
140
+ return nil if empty?
141
+ @size -= 1
142
+ value = cdr.value
143
+ @cdr = cdr.cdr
144
+ @lcdr = nil if empty?
145
+ value
146
+ end
147
+ alias_method :shift, :pop
148
+
149
+ # Initializes this list to the empty state
150
+ def clear
151
+ @cdr, @lcdr, @size = nil, nil, 0
152
+ end
153
+
154
+ # Returns the first value of this list
155
+ def first
156
+ cdr.nil? ? nil : cdr.value
157
+ end
158
+
159
+ # Returns the last value of this list
160
+ def last
161
+ return nil if empty?
162
+ @lcdr.value
163
+ end
164
+
165
+ def concat(other)
166
+ result = new_species
167
+ other.reverse.each do |value|
168
+ result << value
169
+ end
170
+ self.reverse.each do |value|
171
+ result << value
172
+ end
173
+ result
174
+ end
175
+ alias_method :+, :concat
176
+
177
+ # Returns a new instance of the same class as self.
178
+ def new_species
179
+ self.class.new
180
+ end
181
+ protected :new_species
182
+
183
+ # Returns a new node instance.
184
+ def new_node(value, cdr)
185
+ node_class.new(value, cdr)
186
+ end
187
+ protected :new_node
188
+
189
+ # Returns the class of node to use. Defaults to LinkedList::Node.
190
+ def node_class
191
+ LinkedList::Node
192
+ end
193
+ protected :node_class
194
+
195
+ # Returns a nice looking view of this list.
196
+ # list = LinkedList.new
197
+ # list.push "a"
198
+ # list.push "b"
199
+ # list.inspect
200
+ # #=> ("b" ("a" nil))
201
+ def inspect
202
+ cdr.inspect
203
+ end
204
+ end
@@ -0,0 +1,23 @@
1
+ class LinkedList
2
+ # Implements a single node of the linked list.
3
+ class Node
4
+ attr_accessor :cdr, :value
5
+
6
+ def initialize(value, cdr)
7
+ @cdr, @value = cdr, value
8
+ end
9
+
10
+ # Two nodes are equal if their values are equal and their cdr's are equal too.
11
+ def ==(other)
12
+ cdr == other.cdr && value == other.value
13
+ end
14
+
15
+ # Returns a nice-looking string.
16
+ # node = LinkedList::Node.new("a", nil)
17
+ # node.inspect
18
+ # #=> ("a" nil)
19
+ def inspect
20
+ "(#{value.inspect} #{cdr.inspect})"
21
+ end
22
+ end
23
+ end
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/linked_list.rb'}"
9
+ puts "Loading linked_list gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1,74 @@
1
+ namespace :test do
2
+ task :benchmark => %w(test) do
3
+ require "benchmark"
4
+ include Benchmark
5
+ $:.unshift File.dirname(__FILE__) + "/../lib"
6
+ require "linked_list"
7
+
8
+ puts "Building a list of 1 million random strings"
9
+ list = nil
10
+ time = realtime do
11
+ list = list_of_elements(1_000_000)
12
+ end
13
+ puts "Took %.3f seconds" % time
14
+ puts "Converting to an array"
15
+ array = nil
16
+ time = realtime do
17
+ array = list.to_a
18
+ end
19
+ puts "Took %.3f seconds" % time
20
+
21
+ bm(16) do |x|
22
+ x.report("list#push/pop") do
23
+ 20_000.times do
24
+ list.push "a"
25
+ end
26
+ 20_000.times do
27
+ list.pop
28
+ end
29
+ end
30
+ x.report("array#push/pop") do
31
+ 20_000.times do
32
+ array.push "a"
33
+ end
34
+ 20_000.times do
35
+ array.pop
36
+ end
37
+ end
38
+ end
39
+
40
+ bm(16) do |x|
41
+ x.report("list#last") { 20.times { list.last } }
42
+ x.report("array#last") { 20.times { array.last } }
43
+ end
44
+
45
+ bm(16) do |x|
46
+ x.report("list#first") { 2_000.times { list.first } }
47
+ x.report("array#first") { 2_000.times { array.first } }
48
+ end
49
+
50
+ bm(16) do |x|
51
+ x.report("list#reverse") { list.reverse }
52
+ x.report("array#reverse") { array.reverse }
53
+ end
54
+
55
+ bm(16) do |x|
56
+ x.report("list#dup") { list.dup }
57
+ x.report("array#dup") { array.dup }
58
+ end
59
+ end
60
+ end
61
+
62
+ def list_of_elements(count)
63
+ list = LinkedList.new
64
+ count.times do
65
+ list << nil
66
+ end
67
+ list
68
+ end
69
+
70
+ CHARS = ('a' .. 'z').to_a + ('A' .. 'Z').to_a + ('0' .. '9').to_a
71
+ LENGTH = CHARS.length
72
+ def random_string
73
+ (0..10).inject("") {|str, _| str << CHARS[rand(LENGTH)]}
74
+ end
@@ -0,0 +1,6 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../lib/linked_list'
3
+ require "rubygems"
4
+
5
+ gem "francois-shoulda"
6
+ require "shoulda"
@@ -0,0 +1,516 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestLinkedList < Test::Unit::TestCase
4
+ context "An empty LinkedList" do
5
+ setup do
6
+ @list = LinkedList.new
7
+ end
8
+
9
+ context "#push'ing a value of nil" do
10
+ setup do
11
+ @list.push nil
12
+ end
13
+
14
+ should "have a length of 1" do
15
+ assert_equal 1, @list.length
16
+ end
17
+
18
+ should "be equal to [nil]" do
19
+ assert_equal [nil], @list.to_a
20
+ end
21
+ end
22
+
23
+ context "#push'ing an element" do
24
+ setup do
25
+ @list.push "a"
26
+ end
27
+
28
+ should "be equal to ['a']" do
29
+ assert_equal %w(a), @list.to_a
30
+ end
31
+ end
32
+
33
+ context "calling #reverse" do
34
+ setup do
35
+ @other = @list.reverse
36
+ end
37
+
38
+ should "return another list instance" do
39
+ assert_not_same @list, @other
40
+ end
41
+
42
+ should "return an empty list" do
43
+ assert @other.empty?
44
+ end
45
+ end
46
+
47
+ context "calling #to_a" do
48
+ setup do
49
+ @other = @list.to_a
50
+ end
51
+
52
+ should "be an Array" do
53
+ assert_kind_of Array, @other
54
+ end
55
+
56
+ should "be empty" do
57
+ assert @other.empty?
58
+ end
59
+ end
60
+
61
+ should "return nil on #at(0)" do
62
+ assert_nil @list.at(0)
63
+ end
64
+
65
+ should "return nil on #at(-1)" do
66
+ assert_nil @list.at(-1)
67
+ end
68
+
69
+ should "return nil on #[](1)" do
70
+ assert_nil @list[1]
71
+ end
72
+
73
+ should "return nil on #[](-1)" do
74
+ assert_nil @list[-1]
75
+ end
76
+
77
+ should "return nil on #[](0, 1)" do
78
+ assert_equal [], @list[0, 1]
79
+ end
80
+
81
+ should "return nil on #[](0..1)" do
82
+ assert_equal [], @list[0..1]
83
+ end
84
+
85
+ should "return nil on #[](0)" do
86
+ assert_nil @list[0]
87
+ end
88
+
89
+ should "return a new instance when calling #dup" do
90
+ assert_not_same @list, @list.dup
91
+ end
92
+
93
+ should "return nil for #first" do
94
+ assert_nil @list.first
95
+ end
96
+
97
+ should "return nil for #last" do
98
+ assert_nil @list.last
99
+ end
100
+
101
+ should "be empty" do
102
+ assert @list.empty?
103
+ end
104
+
105
+ should "have a length of 0" do
106
+ assert_equal 0, @list.length
107
+ end
108
+
109
+ should "have a size of 0" do
110
+ assert_equal 0, @list.size
111
+ end
112
+
113
+ should "never call the #each block" do
114
+ yielded = 0
115
+ @list.each do |value|
116
+ yielded += 1
117
+ end
118
+ assert yielded.zero?
119
+ end
120
+
121
+ context "calling #concat(['a'])" do
122
+ setup do
123
+ @other = @list.concat(%w(a))
124
+ end
125
+
126
+ should "return a new list" do
127
+ assert_not_same @other, @list
128
+ end
129
+
130
+ should "return a list with one more element" do
131
+ assert_equal @list.length + 1, @other.length
132
+ end
133
+
134
+ should "return a list equal to ('a' nil)" do
135
+ assert_equal LinkedList.new << "a", @other
136
+ end
137
+ end
138
+ end
139
+
140
+ context "A linked list with one element" do
141
+ setup do
142
+ @list = LinkedList.new
143
+ @list << "a"
144
+ end
145
+
146
+ context "calling #pop" do
147
+ setup do
148
+ @element = @list.pop
149
+ end
150
+
151
+ should "be empty?" do
152
+ assert @list.empty?
153
+ end
154
+
155
+ should "return the element" do
156
+ assert_equal "a", @element
157
+ end
158
+
159
+ should "have a size of 0" do
160
+ assert @list.size.zero?
161
+ end
162
+
163
+ should "return nil from #last" do
164
+ assert_nil @list.last
165
+ end
166
+
167
+ should "return nil from #first" do
168
+ assert_nil @list.first
169
+ end
170
+
171
+ context "pushing 'b'" do
172
+ setup do
173
+ @list.push "b"
174
+ end
175
+
176
+ should "NOT be empty" do
177
+ assert !@list.empty?
178
+ end
179
+
180
+ should "be ['b']" do
181
+ assert_equal %w(b), @list.to_a
182
+ end
183
+
184
+ should "return 'b' from #last" do
185
+ assert_equal "b", @list.last
186
+ end
187
+
188
+ should "return 'b' from #first" do
189
+ assert_equal "b", @list.first
190
+ end
191
+ end
192
+ end
193
+
194
+ context "calling #to_a" do
195
+ setup do
196
+ @other = @list.to_a
197
+ end
198
+
199
+ should "be equal to ['a']" do
200
+ assert_equal %w(a), @other
201
+ end
202
+ end
203
+
204
+ context "calling #reverse" do
205
+ setup do
206
+ @other = @list.reverse
207
+ end
208
+
209
+ should "be equal to the initial list" do
210
+ assert_equal @list, @other
211
+ end
212
+ end
213
+
214
+ context "calling #dup" do
215
+ setup do
216
+ @other = @list.dup
217
+ end
218
+
219
+ should "be a new instance" do
220
+ assert_not_same @list, @other
221
+ end
222
+
223
+ should "have duplicated the nodes" do
224
+ @list.map! {|value| value*2}
225
+ assert_not_equal @list, @other
226
+ end
227
+ end
228
+
229
+ should "return 'a' for #at(-1)" do
230
+ assert_equal "a", @list.at(-1)
231
+ end
232
+
233
+ should "return 'a' for #at(0)" do
234
+ assert_equal "a", @list.at(0)
235
+ end
236
+
237
+ should "return nil for #at(2)" do
238
+ assert_nil @list.at(2)
239
+ end
240
+
241
+ should "return nil for #at(-2)" do
242
+ assert_nil @list.at(-2)
243
+ end
244
+
245
+ should "return nil for #at(1)" do
246
+ assert_nil @list.at(1)
247
+ end
248
+
249
+ should "return 'a' for #first" do
250
+ assert_equal "a", @list.first
251
+ end
252
+
253
+ should "return 'a' for #last" do
254
+ assert_equal "a", @list.last
255
+ end
256
+
257
+ should "NOT be empty?" do
258
+ assert !@list.empty?
259
+ end
260
+
261
+ should "have a size of 1" do
262
+ assert_equal 1, @list.size
263
+ end
264
+
265
+ should "yield the single element to the #each block" do
266
+ @list.each do |value|
267
+ assert_equal "a", value
268
+ end
269
+ end
270
+
271
+ should "yield once calling #each" do
272
+ yielded = 0
273
+ @list.each do |value|
274
+ yielded += 1
275
+ end
276
+ assert_equal 1, yielded
277
+ end
278
+
279
+ should "yield the value and the index when calling #each_with_index" do
280
+ yields = []
281
+ @list.each_with_index do |value, index|
282
+ yields << [value, index]
283
+ end
284
+ assert_equal [["a", 0]], yields
285
+ end
286
+
287
+ should "include?('a')" do
288
+ assert @list.include?("a")
289
+ end
290
+
291
+ should "NOT include?('b')" do
292
+ assert !@list.include?("b")
293
+ end
294
+ end
295
+
296
+ context "A list with 2 elements" do
297
+ setup do
298
+ @list = LinkedList.new
299
+ @list << "a"
300
+ @list << "b"
301
+ end
302
+
303
+ context "calling #to_a" do
304
+ setup do
305
+ @other = @list.to_a
306
+ end
307
+
308
+ should "be equal to ['b', 'a']" do
309
+ assert_equal %w(b a), @other
310
+ end
311
+ end
312
+
313
+ context "calling #reverse" do
314
+ setup do
315
+ @other = @list.reverse
316
+ end
317
+
318
+ should "return the elements in insertion order" do
319
+ assert_equal %w(a b), @other.to_a
320
+ end
321
+ end
322
+
323
+ context "cleared" do
324
+ setup do
325
+ @list.clear
326
+ end
327
+
328
+ should "be empty?" do
329
+ assert @list.empty?
330
+ end
331
+ end
332
+
333
+ context "#map" do
334
+ setup do
335
+ @other = @list.map {|f| f*2}
336
+ end
337
+
338
+ should "return a list of 2 elements" do
339
+ assert_equal 2, @other.length
340
+ end
341
+
342
+ should "include?('aa')" do
343
+ assert @other.include?("aa")
344
+ end
345
+
346
+ should "include?('bb')" do
347
+ assert @other.include?("bb")
348
+ end
349
+
350
+ should "NOT have reversed the list" do
351
+ assert_equal %w(bb aa), @other.to_a
352
+ end
353
+ end
354
+
355
+ context "calling #pop" do
356
+ setup do
357
+ @element = @list.pop
358
+ end
359
+
360
+ should "NOT be empty?" do
361
+ assert !@list.empty?
362
+ end
363
+
364
+ should "return the moast recently pushed element" do
365
+ assert_equal "b", @element
366
+ end
367
+
368
+ should "have a size of 1" do
369
+ assert_equal 1, @list.size
370
+ end
371
+ end
372
+
373
+ should "return 'b' for #at(0)" do
374
+ assert_equal "b", @list.at(0)
375
+ end
376
+
377
+ should "return 'a' for #at(1)" do
378
+ assert_equal "a", @list.at(1)
379
+ end
380
+
381
+ should "return 'a' for #at(-1)" do
382
+ assert_equal "a", @list.at(-1)
383
+ end
384
+
385
+ should "return 'b' for #at(-2)" do
386
+ assert_equal "b", @list.at(-2)
387
+ end
388
+
389
+ should "return 'b' for #first" do
390
+ assert_equal "b", @list.first
391
+ end
392
+
393
+ should "return 'a' for #last" do
394
+ assert_equal "a", @list.last
395
+ end
396
+
397
+ should "include?('b')" do
398
+ assert @list.include?("b")
399
+ end
400
+
401
+ should "have a length of 2" do
402
+ assert_equal 2, @list.length
403
+ end
404
+
405
+ should "yield the value and the index when calling #each_with_index" do
406
+ yields = []
407
+ @list.each_with_index do |value, index|
408
+ yields << [value, index]
409
+ end
410
+ assert_equal [["b", 0], ["a", 1]], yields
411
+ end
412
+ end
413
+
414
+ context "A list with 5 elements" do
415
+ setup do
416
+ @list = LinkedList.new
417
+ @list << "a" << "b" << "c" << "d" << "e"
418
+ end
419
+
420
+ should "have a length of 5" do
421
+ assert_equal 5, @list.length
422
+ end
423
+
424
+ should "return 'a' for #at(-1)" do
425
+ assert_equal "a", @list.at(-1)
426
+ end
427
+
428
+ should "return 'e' for #at(-5)" do
429
+ assert_equal "e", @list.at(-5)
430
+ end
431
+
432
+ should "return ['e', 'd', 'c', 'b', 'a'] for #[](0..10)" do
433
+ assert_equal %w(e d c b a), @list[0..10]
434
+ end
435
+
436
+ should "return ['e', 'd'] for #[](0..1)" do
437
+ assert_equal %w(e d), @list[0..1]
438
+ end
439
+
440
+ should "return ['e'] for #[](0..0)" do
441
+ assert_equal %w(e), @list[0..0]
442
+ end
443
+
444
+ should "return ['e', 'd', 'c'] for #[](0..2)" do
445
+ assert_equal %w(e d c), @list[0..2]
446
+ end
447
+
448
+ should "return ['e', 'd', 'c', 'b', 'a'] for #[](0, 10)" do
449
+ assert_equal %w(e d c b a), @list[0, 10]
450
+ end
451
+
452
+ should "return ['e'] for #[](0, 1)" do
453
+ assert_equal %w(e), @list[0, 1]
454
+ end
455
+
456
+ should "return ['e', 'd'] for #[](0, 2)" do
457
+ assert_equal %w(e d), @list[0, 2]
458
+ end
459
+
460
+ should "return nil for #[](-240)" do
461
+ assert_nil @list[-240]
462
+ end
463
+
464
+ should "return nil for #[](240)" do
465
+ assert_nil @list[240]
466
+ end
467
+
468
+ should "return nil for #[](-240, 100)" do
469
+ assert_nil @list[-240, 100]
470
+ end
471
+
472
+ should "return nil for #[](240, 100)" do
473
+ assert_nil @list[240, 100]
474
+ end
475
+
476
+ should "return ['b', 'a'] for #[](-2..-1)" do
477
+ assert_equal %w(b a), @list[-2..-1]
478
+ end
479
+
480
+ should "return ['c', 'b'] for #[](-3, 2)" do
481
+ assert_equal %w(c b), @list[-3, 2]
482
+ end
483
+
484
+ context "calling #concat(['x', 'y', 'z'])" do
485
+ setup do
486
+ @other = @list.concat(%w(x y z))
487
+ end
488
+
489
+ should "return a new list" do
490
+ assert_not_same @list, @other
491
+ end
492
+
493
+ should "return a list of 8 elements" do
494
+ assert_equal 8, @other.length
495
+ end
496
+
497
+ should "return a LinkedList" do
498
+ assert_kind_of LinkedList, @other
499
+ end
500
+
501
+ should "return ['e', 'd', 'c', 'b', 'a', 'x', 'y', 'z']" do
502
+ assert_equal %w(e d c b a x y z), @other.to_a
503
+ end
504
+ end
505
+
506
+ context "calling #+(('z' nil))" do
507
+ setup do
508
+ @other = @list + (LinkedList.new << "z")
509
+ end
510
+
511
+ should "return ['e', 'd', 'c', 'b', 'a', 'z']" do
512
+ assert_equal %w(e d c b a z), @other.to_a
513
+ end
514
+ end
515
+ end
516
+ end
@@ -0,0 +1,41 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestLinkedListNode < Test::Unit::TestCase
4
+ context "A node with the empty string as a value at the end of the chain" do
5
+ setup do
6
+ @node = LinkedList::Node.new("", nil)
7
+ end
8
+
9
+ should "be equal to itself" do
10
+ assert_equal @node, @node
11
+ end
12
+
13
+ should "be equal to another node that is empty" do
14
+ assert_equal @node, LinkedList::Node.new("", nil)
15
+ end
16
+
17
+ should "NOT be equal to another node that has a different value" do
18
+ assert_not_equal @node, LinkedList::Node.new("a", nil)
19
+ end
20
+
21
+ should "NOT be equal to another node that has a different cdr" do
22
+ assert_not_equal @node, LinkedList::Node.new("", LinkedList::Node.new(nil, nil))
23
+ end
24
+
25
+ should "be inspectable" do
26
+ assert_equal "(\"\" nil)", @node.inspect
27
+ end
28
+ end
29
+
30
+ context "A node with a value of 'a' and a successor of 'b'" do
31
+ setup do
32
+ @tail = LinkedList::Node.new("b", nil)
33
+ @head = LinkedList::Node.new("a", @tail)
34
+ end
35
+
36
+ should "be inspectable" do
37
+ assert_equal "(\"a\" (\"b\" nil))", @head.inspect
38
+ end
39
+ end
40
+
41
+ end
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: linked_list
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - "Fran\xC3\xA7ois Beausoleil"
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-11-12 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: newgem
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.0.7
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: francois-shoulda
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.0.5
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: hoe
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.8.0
44
+ version:
45
+ description: A simple linked list implementation that follows Ruby's conventions.
46
+ email:
47
+ - francois@teksol.info
48
+ executables: []
49
+
50
+ extensions: []
51
+
52
+ extra_rdoc_files:
53
+ - History.txt
54
+ - Manifest.txt
55
+ - Benchmarks.txt
56
+ - README.rdoc
57
+ files:
58
+ - History.txt
59
+ - Manifest.txt
60
+ - Benchmarks.txt
61
+ - README.rdoc
62
+ - Rakefile
63
+ - lib/linked_list.rb
64
+ - lib/linked_list/node.rb
65
+ - script/console
66
+ - script/destroy
67
+ - script/generate
68
+ - tasks/benchmark.rake
69
+ - test/test_helper.rb
70
+ - test/test_linked_list.rb
71
+ - test/test_linked_list_node.rb
72
+ has_rdoc: true
73
+ homepage: http://linkedlist.rubyforge.org/
74
+ post_install_message:
75
+ rdoc_options:
76
+ - --main
77
+ - README.rdoc
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: "0"
85
+ version:
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: "0"
91
+ version:
92
+ requirements: []
93
+
94
+ rubyforge_project: linkedlist
95
+ rubygems_version: 1.2.0
96
+ signing_key:
97
+ specification_version: 2
98
+ summary: A simple linked list implementation that follows Ruby's conventions.
99
+ test_files:
100
+ - test/test_helper.rb
101
+ - test/test_linked_list.rb
102
+ - test/test_linked_list_node.rb