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 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
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ gem "rspec", "~> 3.9"
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,2 @@
1
+ require_relative "./circular_linked/node.rb"
2
+ require_relative "./circular_linked/list.rb"
@@ -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,11 @@
1
+ module CircularLinked
2
+ class Node
3
+
4
+ attr_accessor :value, :next
5
+
6
+ def initialize(value, next_node = nil)
7
+ @value = value
8
+ @next = next_node
9
+ end
10
+ end
11
+ 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: []