Skip to content

Commit

Permalink
feat: Finish LinkedList methods
Browse files Browse the repository at this point in the history
  • Loading branch information
BraisonCrece committed Jul 29, 2023
1 parent 021eb5e commit a038ca0
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 99 deletions.
2 changes: 1 addition & 1 deletion .gitignote
Original file line number Diff line number Diff line change
@@ -1 +1 @@
.byebug_history
byebug_history
124 changes: 75 additions & 49 deletions data-structures/LinkedList/linked_list.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,68 +3,94 @@
class LinkedList
attr_accessor :head, :tail

def add(value)
node = Node.new(value)
node.value = value
if !head
@head = node
@tail = node
def append(value)
raise ArgumentError.new("Error: Invalid value") if value.nil?
new_node = Node.new(value)
new_node.previous_node = @tail
@tail.next_node = new_node if @tail
@tail = new_node
@head ||= new_node
"Success: Value '#{value}' was appended"
rescue => exception
warn exception.message
end

def prepend(value)
raise ArgumentError.new("Error: Invalid value") if value.nil?
new_node = Node.new(value)
new_node.next_node = @head
@head.previous_node = new_node if @head
@head = new_node
@tail ||= new_node
"Success: Value '#{value}' was prepended"
rescue => exception
warn exception.message
end

def insert_at(index, value)
raise ArgumentError.new("Error: Invalid value") if value.nil?
raise IndexError.new("Error: Index out of bounds") if index < 0 || index > size
raise StandardError.new("Error: The list is empty") if size == 0

case index
when 0
prepend(value)
when size
append(value)
else
node.previous_node = @tail
@tail.next_node = node
@tail = node
new_node = Node.new(value)
prev_node = select_node(index - 1)
next_node = select_node(index)

prev_node.next_node = new_node
new_node.previous_node = prev_node
new_node.next_node = next_node
next_node.previous_node = new_node
end
"success"
"Success: Value '#{value}' was inserted at index #{index}"
rescue => exception
warn exception.message
end

def get(index)
begin
return @head.value if index === 0
node = select_node(index)
raise "INDEX #{index} OUT OF BOUNDS" if !node
node.value
rescue => exception
p "#{exception.message}"
end
raise StandardError.new("Error: The list is empty") if size === 0
return @head.value if index === 0
node = select_node(index)
raise IndexError.new("Index #{index} out of bounds") if !node
node.value
rescue => exception
warn exception.message
end

def replace(index, new_value)
begin
node_to_replace = select_node(index)
raise "INDEX #{index} OUT OF BOUNDS" if !node_to_replace
# Replace the value directly
node_to_replace.value = new_value
new_value # This should be the replaced node's value
rescue => exception
p "#{exception.message}"
end
raise StandardError.new("Error: The list is empty") if size === 0
node_to_replace = select_node(index)
raise IndexError.new("Index #{index} out of bounds") unless node_to_replace
node_to_replace.value = new_value
rescue => exception
warn exception.message
end

def remove(index)
begin
# if the node is the head
if index === 0
@head.next_node.previous_node = nil
@head = @head.next_node
return
end

node = select_node(index)
raise "INDEX #{index} OUT OF BOUNDS" if !node
# if the node is the tail
if !node.next_node
node.previous_node.next_node = nil
@tail = node.previous_node
return
end
raise StandardError.new("Error: The list is empty") if size === 0
if index === 0
@head.next_node.previous_node = nil
@head = @head.next_node
return
end

# if the node is in the middle
node.previous_node.next_node = node.next_node
node.next_node.previous_node = node.next_node
node = select_node(index)
raise IndexError.new("Index #{index} out of bounds") if !node
if !node.next_node
node.previous_node.next_node = nil
@tail = node.previous_node
return
rescue => exception
p "#{exception.message}"
end

node.previous_node.next_node = node.next_node
node.next_node.previous_node = node.next_node
rescue => exception
warn exception.message
end

def inspect
Expand All @@ -78,7 +104,7 @@ def inspect
end

def size
return 0 if @head === nil
return 0 if @head.nil?
size = 1
node = @head
while node.next_node
Expand Down
170 changes: 121 additions & 49 deletions spec/linked_list_spec.rb
Original file line number Diff line number Diff line change
@@ -1,81 +1,153 @@
# frozen_string_literal: true

require_relative "../data-structures/LinkedList/linked_list"
require "byebug"

RSpec.describe LinkedList do
let(:linked_list) { LinkedList.new }
context "with an empty list" do
describe "#append" do
it "adds a value to the enf of the list" do
expect(subject.append("First Value")).to eq "Success: Value 'First Value' was appended"
expect(subject.head.value).to eq "First Value"
expect(subject.tail.value).to eq "First Value"
expect(subject.size).to eq 1
end
end

describe "#add" do
it "adds a value to the linked list" do
expect(linked_list.add("First Value")).to eq "success"
expect(linked_list.head.value).to eq "First Value"
expect(linked_list.tail.value).to eq "First Value"
describe "#prepend" do
it "adds a value at the start of the list" do
expect(subject.prepend("New first value")).to eq "Success: Value 'New first value' was prepended"
expect(subject.head.value).to eq "New first value"
expect(subject.tail.value).to eq "New first value"
end
end
end

describe "#get" do
it "gets the value at a given index" do
linked_list.add("First Value")
linked_list.add("Second Value")
expect(linked_list.get(1)).to eq "Second Value"
describe "#isert_at" do
it "show an error" do
expect { subject.insert_at(0, "First value") }.to output("Error: The list is empty\n").to_stderr
end
end

it "returns error message if index out of bounds" do
expect(linked_list.get(10)).to eq "INDEX 10 OUT OF BOUNDS"
describe "#get" do
it "returns error message if list is empty" do
expect { subject.get(0) }.to output("Error: The list is empty\n").to_stderr
end
end
end

describe "#replace" do
before do
linked_list.add("First Value")
linked_list.add("Second Value")
describe "#replace" do
it "returns error message if list is empty" do
expect { subject.replace(0, "New Value") }.to output("Error: The list is empty\n").to_stderr
end
end

describe "#remove" do
it "returns error message if the list is empty" do
expect { subject.remove(0) }.to output("Error: The list is empty\n").to_stderr
end
end

it "replaces the value at a given index" do
linked_list.replace(1, "New First Value")
expect(linked_list.get(1)).to eq "New First Value"
describe "#inspect" do
it "prints the linked list" do
expect(subject.inspect).to eq []
end
end

it "returns error message if index out of bounds" do
expect(linked_list.replace(10, "New Value")).to eq "INDEX 10 OUT OF BOUNDS"
describe "#size" do
it "returns 0 if the linked list is empty" do
expect(subject.size).to eq 0
end
end
end

describe "#remove" do
context "whit nodes already in the list" do
before do
linked_list.add("First Value")
linked_list.add("Second Value")
subject.append("First Value")
subject.append("Second Value")
end

it "removes the value at a given index" do
linked_list.remove(0)
expect(linked_list.get(0)).to eq "Second Value"
describe "#append" do
it "adds a value to the enf of the list" do
expect(subject.append("Third Value")).to eq "Success: Value 'Third Value' was appended"
expect(subject.head.value).to eq "First Value"
expect(subject.tail.value).to eq "Third Value"
expect(subject.size).to eq 3
end
end

it "returns error message if index out of bounds" do
expect(linked_list.remove(10)).to eq "INDEX 10 OUT OF BOUNDS"
describe "#prepend" do
it "adds a value at the start of the list" do
expect(subject.prepend("New first value")).to eq "Success: Value 'New first value' was prepended"
expect(subject.head.value).to eq "New first value"
expect(subject.tail.value).to eq "Second Value"
end
end
end

describe "#inspect" do
before do
linked_list.add("First Value")
linked_list.add("Second Value")
describe "#isert_at" do
it "inserts the node on index 0" do
expect(subject.size).to eq 2
expect(subject.insert_at(0, "New node")).to eq "Success: Value 'New node' was inserted at index 0"
expect(subject.head.value).to eq "New node"
expect(subject.size).to eq 3
end

it "inserts the node on the last index" do
expect(subject.size).to eq 2
expect(subject.insert_at(2, "New node")).to eq "Success: Value 'New node' was inserted at index 2"
expect(subject.tail.value).to eq "New node"
expect(subject.size).to eq 3
end

it "inserts the new node in the middle" do
expect(subject.size).to eq 2
expect(subject.insert_at(1, "New node")).to eq "Success: Value 'New node' was inserted at index 1"
expect(subject.head.value).to eq "First Value"
expect(subject.tail.value).to eq "Second Value"
expect(subject.size).to eq 3
end
end

it "prints the linked list" do
expect(linked_list.inspect).to eq ["First Value", "Second Value"]
describe "#get" do
it "gets the value at a given index" do
expect(subject.get(1)).to eq "Second Value"
end

it "returns error message if index out of bounds" do
expect { subject.get(10) }.to output("Index 10 out of bounds\n").to_stderr
end
end

describe "#replace" do
it "replaces the value at a given index" do
subject.replace(1, "New First Value")
expect(subject.get(1)).to eq "New First Value"
end

it "returns error message if index out of bounds" do
expect { subject.replace(10, "New Value") }.to output("Index 10 out of bounds\n").to_stderr
end
end

describe "#remove" do
it "removes the value at a given index" do
subject.remove(0)
expect(subject.get(0)).to eq "Second Value"
end

it "returns error message if index out of bounds" do
expect { subject.remove(10) }.to output("Index 10 out of bounds\n").to_stderr
end
end
end

describe "#size" do
it "returns the size of the linked list" do
linked_list.add("First Value")
linked_list.add("Second Value")
linked_list.add("Third Value")
expect(linked_list.size).to eq 3
describe "#inspect" do
it "prints the linked list" do
expect(subject.inspect).to eq ["First Value", "Second Value"]
end
end

it "returns 0 if the linked list is empty" do
expect(linked_list.size).to eq 0
describe "#size" do
it "returns the size of the linked list" do
subject.append("Third Value")
expect(subject.size).to eq 3
end
end
end
end

0 comments on commit a038ca0

Please sign in to comment.