diff --git a/ruby/linked-list/README.md b/ruby/linked-list/README.md new file mode 100644 index 0000000..41294be --- /dev/null +++ b/ruby/linked-list/README.md @@ -0,0 +1,58 @@ +# Linked List + +Implement a doubly linked list. + +Like an array, a linked list is a simple linear data structure. Several +common data types can be implemented using linked lists, like queues, +stacks, and associative arrays. + +A linked list is a collection of data elements called *nodes*. In a +*singly linked list* each node holds a value and a link to the next node. +In a *doubly linked list* each node also holds a link to the previous +node. + +You will write an implementation of a doubly linked list. Implement a +Node to hold a value and pointers to the next and previous nodes. Then +implement a List which holds references to the first and last node and +offers an array-like interface for adding and removing items: + +* `push` (*insert value at back*); +* `pop` (*remove value at back*); +* `shift` (*remove value at front*). +* `unshift` (*insert value at front*); + +To keep your implementation simple, the tests will not cover error +conditions. Specifically: `pop` or `shift` will never be called on an +empty list. + +If you want to know more about linked lists, check [Wikipedia](https://en.wikipedia.org/wiki/Linked_list). + +* * * * + +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 linked_list_test.rb + +To include color from the command line: + + ruby -r minitest/pride linked_list_test.rb + + +## Source + +Classic computer science topic + +## Submitting Incomplete Solutions +It's possible to submit an incomplete solution so you can see how others have completed the exercise. diff --git a/ruby/linked-list/linked_list.rb b/ruby/linked-list/linked_list.rb new file mode 100644 index 0000000..b51f923 --- /dev/null +++ b/ruby/linked-list/linked_list.rb @@ -0,0 +1,48 @@ +# Deque class +class Deque + def initialize + @front = nil + @back = nil + end + + def push(data) + element = Element.new(data) + element.prev = @back + @back.next = element if @back + @back = element + @front = element if @front.nil? + end + + def pop + element = @back + @back = element.prev + @front = nil if @back.nil? + element.data + end + + def unshift(data) + element = Element.new(data) + element.next = @front + @front.prev = element if @front + @front = element + @back = element if @back.nil? + end + + def shift + element = @front + @front = element.next + @back = nil if @front.nil? + element.data + end +end + +# Element class +class Element + attr_accessor :data, :next, :prev + + def initialize(data) + @data = data + @next = nil + @prev = nil + end +end diff --git a/ruby/linked-list/linked_list_test.rb b/ruby/linked-list/linked_list_test.rb new file mode 100644 index 0000000..9bb5c1f --- /dev/null +++ b/ruby/linked-list/linked_list_test.rb @@ -0,0 +1,73 @@ +require 'minitest/autorun' +require_relative 'linked_list' + +class DequeTest < Minitest::Test + def test_push_pop + # skip + deque = Deque.new + deque.push(10) + deque.push(20) + assert_equal 20, deque.pop + assert_equal 10, deque.pop + end + + def test_push_shift + # skip + deque = Deque.new + deque.push(10) + deque.push(20) + assert_equal 10, deque.shift + assert_equal 20, deque.shift + end + + def test_unshift_shift + # skip + deque = Deque.new + deque.unshift(10) + deque.unshift(20) + assert_equal 20, deque.shift + assert_equal 10, deque.shift + end + + def test_unshift_pop + # skip + deque = Deque.new + deque.unshift(10) + deque.unshift(20) + assert_equal 10, deque.pop + assert_equal 20, deque.pop + end + + def test_example + # skip + deque = Deque.new + deque.push(10) + deque.push(20) + assert_equal 20, deque.pop + deque.push(30) + assert_equal 10, deque.shift + deque.unshift(40) + deque.push(50) + assert_equal 40, deque.shift + assert_equal 50, deque.pop + assert_equal 30, deque.shift + end + + def test_pop_to_empty + # skip + deque = Deque.new + deque.push(10) + assert_equal 10, deque.pop + deque.push(20) + assert_equal 20, deque.shift + end + + def test_shift_to_empty + # skip + deque = Deque.new + deque.unshift(10) + assert_equal 10, deque.shift + deque.unshift(20) + assert_equal 20, deque.pop + end +end