ruby - simple-linked-list

This commit is contained in:
James Walker 2018-12-03 20:41:38 -05:00
parent b54cd4cc6a
commit 458588cbb6
Signed by: walkah
GPG Key ID: 3C127179D6086E93
3 changed files with 248 additions and 0 deletions

View 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.

View 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

View 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