ruby - simple-linked-list
This commit is contained in:
parent
b54cd4cc6a
commit
458588cbb6
52
ruby/simple-linked-list/README.md
Normal file
52
ruby/simple-linked-list/README.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# Simple Linked List
|
||||||
|
|
||||||
|
Write a simple linked list implementation that uses Elements and a List.
|
||||||
|
|
||||||
|
The linked list is a fundamental data structure in computer science,
|
||||||
|
often used in the implementation of other data structures. They're
|
||||||
|
pervasive in functional programming languages, such as Clojure, Erlang,
|
||||||
|
or Haskell, but far less common in imperative languages such as Ruby or
|
||||||
|
Python.
|
||||||
|
|
||||||
|
The simplest kind of linked list is a singly linked list. Each element in the
|
||||||
|
list contains data and a "next" field pointing to the next element in the list
|
||||||
|
of elements.
|
||||||
|
|
||||||
|
This variant of linked lists is often used to represent sequences or
|
||||||
|
push-down stacks (also called a LIFO stack; Last In, First Out).
|
||||||
|
|
||||||
|
As a first take, lets create a singly linked list to contain the range (1..10),
|
||||||
|
and provide functions to reverse a linked list and convert to and from arrays.
|
||||||
|
|
||||||
|
When implementing this in a language with built-in linked lists,
|
||||||
|
implement your own abstract data type.
|
||||||
|
|
||||||
|
* * * *
|
||||||
|
|
||||||
|
For installation and learning resources, refer to the
|
||||||
|
[Ruby resources page](http://exercism.io/languages/ruby/resources).
|
||||||
|
|
||||||
|
For running the tests provided, you will need the Minitest gem. Open a
|
||||||
|
terminal window and run the following command to install minitest:
|
||||||
|
|
||||||
|
gem install minitest
|
||||||
|
|
||||||
|
If you would like color output, you can `require 'minitest/pride'` in
|
||||||
|
the test file, or note the alternative instruction, below, for running
|
||||||
|
the test file.
|
||||||
|
|
||||||
|
Run the tests from the exercise directory using the following command:
|
||||||
|
|
||||||
|
ruby simple_linked_list_test.rb
|
||||||
|
|
||||||
|
To include color from the command line:
|
||||||
|
|
||||||
|
ruby -r minitest/pride simple_linked_list_test.rb
|
||||||
|
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
Inspired by 'Data Structures and Algorithms with Object-Oriented Design Patterns in Ruby', singly linked-lists. [http://www.brpreiss.com/books/opus8/html/page96.html#SECTION004300000000000000000](http://www.brpreiss.com/books/opus8/html/page96.html#SECTION004300000000000000000)
|
||||||
|
|
||||||
|
## Submitting Incomplete Solutions
|
||||||
|
It's possible to submit an incomplete solution so you can see how others have completed the exercise.
|
54
ruby/simple-linked-list/simple_linked_list.rb
Normal file
54
ruby/simple-linked-list/simple_linked_list.rb
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# Class Element
|
||||||
|
class Element
|
||||||
|
attr_accessor :datum, :next
|
||||||
|
|
||||||
|
def initialize(datum)
|
||||||
|
@datum = datum
|
||||||
|
@next = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Class SimpleLinkedList
|
||||||
|
class SimpleLinkedList
|
||||||
|
def initialize(stack = [])
|
||||||
|
@tail = nil
|
||||||
|
stack.each do |data|
|
||||||
|
element = Element.new(data)
|
||||||
|
push(element)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def push(element)
|
||||||
|
element.next = @tail
|
||||||
|
@tail = element
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def pop
|
||||||
|
popped = @tail
|
||||||
|
return popped if @tail.nil?
|
||||||
|
|
||||||
|
@tail = popped.next
|
||||||
|
popped
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_a
|
||||||
|
arr = []
|
||||||
|
while @tail
|
||||||
|
element = pop
|
||||||
|
arr.push(element.datum)
|
||||||
|
end
|
||||||
|
arr
|
||||||
|
end
|
||||||
|
|
||||||
|
def reverse!
|
||||||
|
new_tail = nil
|
||||||
|
while @tail
|
||||||
|
element = pop
|
||||||
|
element.next = new_tail
|
||||||
|
new_tail = element
|
||||||
|
end
|
||||||
|
@tail = new_tail
|
||||||
|
self
|
||||||
|
end
|
||||||
|
end
|
142
ruby/simple-linked-list/simple_linked_list_test.rb
Normal file
142
ruby/simple-linked-list/simple_linked_list_test.rb
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
require 'minitest/autorun'
|
||||||
|
require_relative 'simple_linked_list'
|
||||||
|
|
||||||
|
class LinkedListTest < Minitest::Test
|
||||||
|
def test_element
|
||||||
|
element = Element.new(1)
|
||||||
|
assert_equal 1, element.datum
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_element_can_hold_a_different_value
|
||||||
|
# skip
|
||||||
|
element = Element.new(10)
|
||||||
|
assert_equal 10, element.datum
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_element_next
|
||||||
|
# skip
|
||||||
|
element = Element.new(1)
|
||||||
|
assert_nil element.next
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_element_next_can_be_assigned_to
|
||||||
|
# skip
|
||||||
|
first = Element.new(1)
|
||||||
|
second = Element.new(2)
|
||||||
|
first.next = second
|
||||||
|
assert_equal second, first.next
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_list_push
|
||||||
|
# skip
|
||||||
|
list = SimpleLinkedList.new
|
||||||
|
element = Element.new(1)
|
||||||
|
assert_equal list, list.push(element)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_list_pop
|
||||||
|
# skip
|
||||||
|
list = SimpleLinkedList.new
|
||||||
|
element = Element.new(1)
|
||||||
|
list.push(element)
|
||||||
|
assert_equal element, list.pop
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_list_pop_empty
|
||||||
|
# skip
|
||||||
|
list = SimpleLinkedList.new
|
||||||
|
assert_nil list.pop
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_list_pop_is_last_in_first_out
|
||||||
|
# skip
|
||||||
|
list = SimpleLinkedList.new
|
||||||
|
first = Element.new(1)
|
||||||
|
second = Element.new(2)
|
||||||
|
list.push(first).push(second)
|
||||||
|
assert_equal second, list.pop
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_list_empty_to_array
|
||||||
|
# skip
|
||||||
|
list = SimpleLinkedList.new
|
||||||
|
assert_equal [], list.to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_list_single_to_array
|
||||||
|
# skip
|
||||||
|
list = SimpleLinkedList.new
|
||||||
|
first = Element.new(1)
|
||||||
|
list.push(first)
|
||||||
|
assert_equal [1], list.to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_list_multiple_to_array
|
||||||
|
# skip
|
||||||
|
list = SimpleLinkedList.new
|
||||||
|
first = Element.new(1)
|
||||||
|
second = Element.new(2)
|
||||||
|
third = Element.new(3)
|
||||||
|
list.push(first).push(second).push(third)
|
||||||
|
assert_equal [3, 2, 1], list.to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_list_create_from_array
|
||||||
|
# skip
|
||||||
|
array = [1, 2, 3]
|
||||||
|
list = SimpleLinkedList.new(array)
|
||||||
|
assert_equal [3, 2, 1], list.to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_list_created_from_array_still_made_up_of_elements
|
||||||
|
# skip
|
||||||
|
array = [1, 2, 3]
|
||||||
|
list = SimpleLinkedList.new(array)
|
||||||
|
assert_equal Element, list.pop.class
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_list_from_array_still_acts_as_lifo
|
||||||
|
# skip
|
||||||
|
array = [1, 2, 3]
|
||||||
|
list = SimpleLinkedList.new(array)
|
||||||
|
element = list.pop
|
||||||
|
assert_equal 3, element.datum
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_list_in_place_reverse!
|
||||||
|
# skip
|
||||||
|
first = Element.new(1)
|
||||||
|
second = Element.new(2)
|
||||||
|
third = Element.new(3)
|
||||||
|
list = SimpleLinkedList.new
|
||||||
|
list.push(first).push(second).push(third)
|
||||||
|
|
||||||
|
assert_equal [1, 2, 3], list.reverse!.to_a
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_list_in_place_reverse_are_the_same_elements
|
||||||
|
# skip
|
||||||
|
first = Element.new(1)
|
||||||
|
second = Element.new(2)
|
||||||
|
list = SimpleLinkedList.new
|
||||||
|
list.push(first).push(second)
|
||||||
|
|
||||||
|
list.reverse!
|
||||||
|
|
||||||
|
assert_equal first, list.pop
|
||||||
|
assert_equal second, list.pop
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_list_reverse_empty_list
|
||||||
|
# skip
|
||||||
|
list = SimpleLinkedList.new
|
||||||
|
assert_equal list, list.reverse!
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_works_for_1_through_10
|
||||||
|
# skip
|
||||||
|
list = SimpleLinkedList.new(1..10)
|
||||||
|
expected = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
|
||||||
|
assert_equal expected, list.to_a
|
||||||
|
end
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user