circular_linked 0.0.1
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.
- checksums.yaml +7 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +26 -0
- data/lib/circular_linked.rb +2 -0
- data/lib/circular_linked/list.rb +84 -0
- data/lib/circular_linked/node.rb +11 -0
- data/spec/circular_linked/list_spec.rb +185 -0
- data/spec/circular_linked/node_spec.rb +27 -0
- metadata +50 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 7eaddc29746a2d99c05aadcf1e490004f23683178dc49afd5293656c3edceded
|
|
4
|
+
data.tar.gz: 3c906b3079d972ceadad706bcb3cf93749600c24d3b4ebbad7f91cd19df91555
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d583d18873400eec464d1d708aa3b1d4791c1cc38af6b824a2b9f904be4633882b42eaeda58627608159e6da40f58eed5051824c38cc03f34ca6051b187f513b
|
|
7
|
+
data.tar.gz: 2034ffcd127a04c5d6b1e4a9fce71580b4caddddf6c92525399fb57e036a8ab931ee4f4e3a72e2e792732894fdfb1578fcbdc6ee707436b4df7d271a08a7344e
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
GEM
|
|
2
|
+
remote: https://rubygems.org/
|
|
3
|
+
specs:
|
|
4
|
+
diff-lcs (1.4.4)
|
|
5
|
+
rspec (3.10.0)
|
|
6
|
+
rspec-core (~> 3.10.0)
|
|
7
|
+
rspec-expectations (~> 3.10.0)
|
|
8
|
+
rspec-mocks (~> 3.10.0)
|
|
9
|
+
rspec-core (3.10.1)
|
|
10
|
+
rspec-support (~> 3.10.0)
|
|
11
|
+
rspec-expectations (3.10.1)
|
|
12
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
13
|
+
rspec-support (~> 3.10.0)
|
|
14
|
+
rspec-mocks (3.10.2)
|
|
15
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
16
|
+
rspec-support (~> 3.10.0)
|
|
17
|
+
rspec-support (3.10.2)
|
|
18
|
+
|
|
19
|
+
PLATFORMS
|
|
20
|
+
x86_64-linux
|
|
21
|
+
|
|
22
|
+
DEPENDENCIES
|
|
23
|
+
rspec (~> 3.9)
|
|
24
|
+
|
|
25
|
+
BUNDLED WITH
|
|
26
|
+
2.2.7
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
module CircularLinked
|
|
2
|
+
class List
|
|
3
|
+
|
|
4
|
+
attr_accessor :head
|
|
5
|
+
|
|
6
|
+
def initialize(*values)
|
|
7
|
+
nodes = values.map {|v| Node.new(v) }
|
|
8
|
+
@head = nodes.first
|
|
9
|
+
nodes.each_with_index {|node, i| node.next = nodes[i+1] || @head }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def add(value)
|
|
13
|
+
new_node = Node.new(value, head)
|
|
14
|
+
|
|
15
|
+
@head ||= new_node
|
|
16
|
+
new_node.next ||= head
|
|
17
|
+
|
|
18
|
+
last_node.next = new_node
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def last_node
|
|
22
|
+
return nil unless head
|
|
23
|
+
|
|
24
|
+
node = head
|
|
25
|
+
node = node.next while node.next != head
|
|
26
|
+
node
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def find(value)
|
|
30
|
+
return nil unless head
|
|
31
|
+
|
|
32
|
+
node = head
|
|
33
|
+
while node.value != value
|
|
34
|
+
node = node.next
|
|
35
|
+
return nil if node == head
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
node
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def remove(value)
|
|
42
|
+
node = find(value)
|
|
43
|
+
return unless node
|
|
44
|
+
|
|
45
|
+
if head.next == head
|
|
46
|
+
@head = nil
|
|
47
|
+
return
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
node_before = head
|
|
51
|
+
node_before = node_before.next while node_before.next != node
|
|
52
|
+
node_before.next = node.next
|
|
53
|
+
|
|
54
|
+
@head = node.next if node == head
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def items_value
|
|
58
|
+
values = []
|
|
59
|
+
return values unless head
|
|
60
|
+
|
|
61
|
+
each {|node| values.push(node.value) }
|
|
62
|
+
values
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def length
|
|
66
|
+
length = 0
|
|
67
|
+
return length unless head
|
|
68
|
+
|
|
69
|
+
each { length += 1 }
|
|
70
|
+
length
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def each
|
|
74
|
+
return unless head
|
|
75
|
+
|
|
76
|
+
node = head
|
|
77
|
+
loop do
|
|
78
|
+
yield(node)
|
|
79
|
+
node = node.next
|
|
80
|
+
break if node == head
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
require_relative '../../lib/circular_linked/node.rb'
|
|
2
|
+
require_relative '../../lib/circular_linked/list.rb'
|
|
3
|
+
|
|
4
|
+
RSpec.describe CircularLinked::List do
|
|
5
|
+
let(:value1) { "Node1" }
|
|
6
|
+
let(:value2) { "Node2" }
|
|
7
|
+
let(:value3) { "Node3" }
|
|
8
|
+
let(:empty_list) { described_class.new }
|
|
9
|
+
let(:head_list) { described_class.new(value1) }
|
|
10
|
+
let(:two_item_list) { described_class.new(value1, value2) }
|
|
11
|
+
let(:three_item_list) { described_class.new(value1, value2, value3) }
|
|
12
|
+
|
|
13
|
+
describe "#initialize" do
|
|
14
|
+
context "with no params" do
|
|
15
|
+
it "just initializes empty list" do
|
|
16
|
+
expect(empty_list.head).to eq(nil)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "with 1 item" do
|
|
21
|
+
it "initializes list with just a head" do
|
|
22
|
+
expect(head_list.head.value).to eq(value1)
|
|
23
|
+
expect(head_list.head.next).to eq(head_list.head)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context "with two items" do
|
|
28
|
+
it "initializes a circular list" do
|
|
29
|
+
expect(two_item_list.head.value).to eq(value1)
|
|
30
|
+
expect(two_item_list.head.next.value).to eq(value2)
|
|
31
|
+
expect(two_item_list.head.next.next).to eq(two_item_list.head)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe "#last_node" do
|
|
37
|
+
context "when list is empty" do
|
|
38
|
+
it "returns nil" do
|
|
39
|
+
expect(empty_list.last_node).to eq(nil)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
context "when list has only head" do
|
|
44
|
+
it "returns head" do
|
|
45
|
+
expect(head_list.last_node.value).to eq(value1)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
context "when list has three nodes" do
|
|
50
|
+
it "returns last node" do
|
|
51
|
+
expect(three_item_list.last_node.value).to eq(value3)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe "#add" do
|
|
57
|
+
let(:new_value) { "New Value" }
|
|
58
|
+
|
|
59
|
+
context "when list is empty" do
|
|
60
|
+
it "adds the element as the head" do
|
|
61
|
+
expect{empty_list.add(new_value)}.to change{empty_list.head&.value}
|
|
62
|
+
.from(nil).to(new_value)
|
|
63
|
+
expect(empty_list.head.next).to eq(empty_list.head)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context "when list has only head" do
|
|
68
|
+
it "adds another element" do
|
|
69
|
+
expect{head_list.add(new_value)}.to change{head_list.last_node.value}
|
|
70
|
+
.from(head_list.head.value).to(new_value)
|
|
71
|
+
expect(head_list.head.next).not_to eq(head_list.head)
|
|
72
|
+
expect(head_list.last_node.next).to eq(head_list.head)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
context "when list has already three nodes" do
|
|
77
|
+
let!(:old_last_node) { three_item_list.last_node }
|
|
78
|
+
|
|
79
|
+
it "adds fourth node" do
|
|
80
|
+
expect{three_item_list.add(new_value)}.to change{three_item_list.last_node.value}
|
|
81
|
+
.from(old_last_node.value).to(new_value)
|
|
82
|
+
expect(old_last_node.next).not_to eq(three_item_list.head)
|
|
83
|
+
expect(three_item_list.last_node.next).to eq(three_item_list.head)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
describe "#find" do
|
|
89
|
+
let(:value_outside_list) { "MissingNode" }
|
|
90
|
+
|
|
91
|
+
context "when list is empty" do
|
|
92
|
+
it "returns nil" do
|
|
93
|
+
expect(empty_list.find(value_outside_list)).to eq(nil)
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
context "when list has only head" do
|
|
98
|
+
it "returns nil if head is not the element" do
|
|
99
|
+
expect(head_list.find(value_outside_list)).to eq(nil)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
it "returns the node if head is the element" do
|
|
103
|
+
expect(head_list.find(value1)).to eq(head_list.head)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
context "when list has three elements" do
|
|
108
|
+
it "returns nil if value is not in list" do
|
|
109
|
+
expect(three_item_list.find(value_outside_list)).to eq(nil)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it "returns the node if value is in list" do
|
|
113
|
+
expect(three_item_list.find(value3)).to eq(three_item_list.last_node)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
describe "#remove" do
|
|
119
|
+
context "when trying to remove non existing value" do
|
|
120
|
+
it "does nothing" do
|
|
121
|
+
expect{two_item_list.remove("Non existing Node")}.not_to change{two_item_list.head}
|
|
122
|
+
expect{two_item_list.remove("Non existing Node")}.not_to change{two_item_list.head.next}
|
|
123
|
+
expect{empty_list.remove("Non existing Node")}.not_to change{empty_list.head}
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
context "when removing a value" do
|
|
128
|
+
it "removes the node and update the links" do
|
|
129
|
+
expect{three_item_list.remove(value2)}.to change{three_item_list.head.next.value}
|
|
130
|
+
.from(value2).to(value3)
|
|
131
|
+
expect(three_item_list.find(value2)).to eq(nil)
|
|
132
|
+
expect(three_item_list.head.value).to eq(value1)
|
|
133
|
+
expect(three_item_list.last_node.value).to eq(value3)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it "removes the head when is a head_list" do
|
|
137
|
+
head_list.remove(value1)
|
|
138
|
+
expect(head_list.head).to eq(nil)
|
|
139
|
+
expect(head_list.find(value1)).to eq(nil)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "removes the head when the removed value is the head" do
|
|
143
|
+
expect{two_item_list.remove(value1)}.to change{two_item_list.head.value}
|
|
144
|
+
.from(value1).to(value2)
|
|
145
|
+
expect(two_item_list.find(value1)).to eq(nil)
|
|
146
|
+
expect(two_item_list.last_node.value).to eq(value2)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it "removes the last note when the removed value is it" do
|
|
150
|
+
expect{three_item_list.remove(value3)}.to change{three_item_list.head.next.next.value}
|
|
151
|
+
.from(value3).to(value1)
|
|
152
|
+
expect(three_item_list.find(value3)).to eq(nil)
|
|
153
|
+
expect(three_item_list.head.value).to eq(value1)
|
|
154
|
+
expect(three_item_list.last_node.value).to eq(value2)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
describe "#items_value" do
|
|
160
|
+
context "when list is empty" do
|
|
161
|
+
it "returns empty array" do
|
|
162
|
+
expect(empty_list.items_value).to eq([])
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
context "when list has only head" do
|
|
167
|
+
it "returns array with one value" do
|
|
168
|
+
expect(head_list.items_value).to eq([value1])
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
context "when list has three items" do
|
|
173
|
+
it "returns array with three values" do
|
|
174
|
+
expect(three_item_list.items_value).to eq([value1, value2, value3])
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
describe "#length" do
|
|
180
|
+
it { expect(empty_list.length).to eq(0) }
|
|
181
|
+
it { expect(head_list.length).to eq(1) }
|
|
182
|
+
it { expect(two_item_list.length).to eq(2) }
|
|
183
|
+
it { expect(three_item_list.length).to eq(3) }
|
|
184
|
+
end
|
|
185
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require_relative '../../lib/circular_linked/node.rb'
|
|
2
|
+
|
|
3
|
+
RSpec.describe CircularLinked::Node do
|
|
4
|
+
describe "#initialize" do
|
|
5
|
+
let(:value) { "Value" }
|
|
6
|
+
|
|
7
|
+
context "when there is no next_node" do
|
|
8
|
+
let(:value) { "Value" }
|
|
9
|
+
subject(:new_node) { described_class.new(value) }
|
|
10
|
+
|
|
11
|
+
it "saves the params passed" do
|
|
12
|
+
expect(new_node.value).to eq(value)
|
|
13
|
+
expect(new_node.next).to eq(nil)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
context "when there is next_node" do
|
|
18
|
+
let(:next_node) { described_class.new("Next node value")}
|
|
19
|
+
subject(:new_node) { described_class.new(value, next_node) }
|
|
20
|
+
|
|
21
|
+
it "saves the params passed" do
|
|
22
|
+
expect(new_node.value).to eq(value)
|
|
23
|
+
expect(new_node.next).to eq(next_node)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: circular_linked
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Gabriela Guedes
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2021-02-02 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description: Provides a circular linked list data structure for Ruby with the most
|
|
14
|
+
common methods
|
|
15
|
+
email: gabriela.guedes.gmg@gmail.com
|
|
16
|
+
executables: []
|
|
17
|
+
extensions: []
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- Gemfile
|
|
21
|
+
- Gemfile.lock
|
|
22
|
+
- lib/circular_linked.rb
|
|
23
|
+
- lib/circular_linked/list.rb
|
|
24
|
+
- lib/circular_linked/node.rb
|
|
25
|
+
- spec/circular_linked/list_spec.rb
|
|
26
|
+
- spec/circular_linked/node_spec.rb
|
|
27
|
+
homepage:
|
|
28
|
+
licenses:
|
|
29
|
+
- MIT
|
|
30
|
+
metadata: {}
|
|
31
|
+
post_install_message:
|
|
32
|
+
rdoc_options: []
|
|
33
|
+
require_paths:
|
|
34
|
+
- lib
|
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
41
|
+
requirements:
|
|
42
|
+
- - ">="
|
|
43
|
+
- !ruby/object:Gem::Version
|
|
44
|
+
version: '0'
|
|
45
|
+
requirements: []
|
|
46
|
+
rubygems_version: 3.2.3
|
|
47
|
+
signing_key:
|
|
48
|
+
specification_version: 4
|
|
49
|
+
summary: Circular Linked List implementation
|
|
50
|
+
test_files: []
|