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