ds 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rubocop.yml +11 -0
- data/.rubocop_todo.yml +452 -0
- data/.travis.yml +12 -0
- data/Gemfile +1 -1
- data/README.rdoc +185 -214
- data/Rakefile +8 -3
- data/ds.gemspec +16 -13
- data/lib/ds.rb +20 -30
- data/lib/ds/{matrixes → arrays}/array_2d.rb +9 -10
- data/lib/ds/arrays/expandable_array.rb +34 -0
- data/lib/ds/arrays/heap_store.rb +32 -0
- data/lib/ds/arrays/tri_matrix.rb +33 -0
- data/lib/ds/lists/list.rb +310 -186
- data/lib/ds/lists/list_element.rb +14 -11
- data/lib/ds/pair.rb +4 -4
- data/lib/ds/queues/priority_queue.rb +33 -20
- data/lib/ds/queues/simple_queue.rb +55 -0
- data/lib/ds/sets/indexed_set.rb +37 -0
- data/lib/ds/stacks/stack.rb +25 -17
- data/lib/ds/trees/binary_heap.rb +71 -66
- data/lib/ds/trees/binary_tree.rb +40 -44
- data/lib/ds/trees/red_black_tree.rb +123 -0
- data/lib/ds/trees/red_black_tree/node.rb +21 -0
- data/lib/ds/trees/tree.rb +50 -48
- data/lib/ds/trees/tree_walker.rb +73 -144
- data/lib/ds/trees/trie.rb +67 -37
- data/lib/ds/trees/trie/node.rb +48 -0
- data/lib/ds/version.rb +2 -1
- data/test/help.rb +3 -6
- data/test/performance/binary_heap_performance_test.rb +20 -0
- data/test/performance/list_performance_test.rb +36 -0
- data/test/performance/priority_queue_performance.rb +32 -0
- data/test/performance/rbt_performance_test.rb +17 -0
- data/test/performance/simple_queue_performance_test.rb +37 -0
- data/test/performance/stack_test.rb +45 -0
- data/test/test_array2d.rb +29 -31
- data/test/test_binary_heap.rb +29 -23
- data/test/test_binary_tree.rb +30 -20
- data/test/test_expandable_array.rb +6 -10
- data/test/test_heap_store.rb +34 -0
- data/test/test_indexed_set.rb +26 -0
- data/test/test_list.rb +226 -109
- data/test/test_list_element.rb +34 -16
- data/test/test_pair.rb +5 -8
- data/test/test_priority_queue.rb +43 -64
- data/test/test_queue.rb +12 -61
- data/test/test_red_black_tree.rb +46 -0
- data/test/test_stack.rb +35 -39
- data/test/test_tree.rb +42 -29
- data/test/test_tree_walker.rb +27 -52
- data/test/test_tri_matrix.rb +6 -11
- data/test/test_trie.rb +59 -17
- metadata +80 -35
- data/lib/ds/ext/array_x.rb +0 -35
- data/lib/ds/graphs/digraph.rb +0 -20
- data/lib/ds/graphs/edge.rb +0 -15
- data/lib/ds/graphs/graph.rb +0 -111
- data/lib/ds/graphs/graph_as_matrix.rb +0 -113
- data/lib/ds/graphs/graph_as_tri_matrix.rb +0 -24
- data/lib/ds/lists/cyclic_list.rb +0 -21
- data/lib/ds/lists/ring.rb +0 -42
- data/lib/ds/matrixes/expandable_array.rb +0 -37
- data/lib/ds/matrixes/tri_matrix.rb +0 -30
- data/lib/ds/queues/queue.rb +0 -53
- data/lib/ds/sets/ordered_set.rb +0 -32
- data/lib/ds/trees/binary_search_tree.rb +0 -34
- data/lib/ds/trees/complete_binary_tree.rb +0 -60
- data/test/test_array_x.rb +0 -51
- data/test/test_binary_search_tree.rb +0 -39
- data/test/test_complete_binary_tree.rb +0 -58
- data/test/test_digraph.rb +0 -134
- data/test/test_graph.rb +0 -80
- data/test/test_ordered_set.rb +0 -28
- data/test/test_ring.rb +0 -28
    
        data/Rakefile
    CHANGED
    
    | @@ -4,10 +4,15 @@ require 'rake/testtask' | |
| 4 4 | 
             
            Rake::TestTask.new do |t|
         | 
| 5 5 | 
             
              t.libs << 'test'
         | 
| 6 6 | 
             
              t.test_files = FileList['test/test*.rb']
         | 
| 7 | 
            -
              #t.pattern = "test/test_*.rb"
         | 
| 8 7 | 
             
              t.verbose = true
         | 
| 9 8 | 
             
            end
         | 
| 10 9 |  | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 10 | 
            +
            Rake::TestTask.new do |t|
         | 
| 11 | 
            +
              t.name = 'test:performance'
         | 
| 12 | 
            +
              t.libs << 'test'
         | 
| 13 | 
            +
              t.test_files = FileList['test/performance/*test.rb']
         | 
| 14 | 
            +
              t.verbose = true
         | 
| 15 | 
            +
            end
         | 
| 13 16 |  | 
| 17 | 
            +
            desc 'Run tests'
         | 
| 18 | 
            +
            task default: :test
         | 
    
        data/ds.gemspec
    CHANGED
    
    | @@ -1,20 +1,23 @@ | |
| 1 1 | 
             
            # -*- encoding: utf-8 -*-
         | 
| 2 | 
            -
            $:.push File.expand_path( | 
| 3 | 
            -
            require  | 
| 2 | 
            +
            $:.push File.expand_path('../lib', __FILE__)
         | 
| 3 | 
            +
            require 'ds/version'
         | 
| 4 4 |  | 
| 5 5 | 
             
            Gem::Specification.new do |s|
         | 
| 6 | 
            -
              s.name        =  | 
| 6 | 
            +
              s.name        = 'ds'
         | 
| 7 7 | 
             
              s.version     = DS::VERSION
         | 
| 8 | 
            -
              s.authors     = [ | 
| 9 | 
            -
              s.email       = [ | 
| 10 | 
            -
              s.homepage    =  | 
| 11 | 
            -
              s.summary     =  | 
| 12 | 
            -
              s.description =  | 
| 13 | 
            -
             | 
| 14 | 
            -
              s.rubyforge_project = "ds"
         | 
| 8 | 
            +
              s.authors     = ['knife']
         | 
| 9 | 
            +
              s.email       = ['satre@o2.pl']
         | 
| 10 | 
            +
              s.homepage    = ''
         | 
| 11 | 
            +
              s.summary     = 'Some common data structures.'
         | 
| 12 | 
            +
              s.description = 'Data structures (lists, stacks, trees, heaps, graphs..) in pure Ruby.'
         | 
| 13 | 
            +
              s.rubyforge_project = 'ds'
         | 
| 15 14 |  | 
| 16 15 | 
             
              s.files         = `git ls-files`.split("\n")
         | 
| 17 | 
            -
              s.test_files    = `git ls-files --  | 
| 18 | 
            -
              s.executables   = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
         | 
| 19 | 
            -
              s.require_paths = [ | 
| 16 | 
            +
              s.test_files    = `git ls-files -- test/**/*`.split("\n")
         | 
| 17 | 
            +
              s.executables   = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
         | 
| 18 | 
            +
              s.require_paths = ['lib']
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              s.add_development_dependency 'bundler'
         | 
| 21 | 
            +
              s.add_development_dependency 'rake'
         | 
| 22 | 
            +
              s.add_development_dependency 'minitest'
         | 
| 20 23 | 
             
            end
         | 
    
        data/lib/ds.rb
    CHANGED
    
    | @@ -1,36 +1,26 @@ | |
| 1 | 
            -
            require  | 
| 1 | 
            +
            require 'ds/version'
         | 
| 2 2 |  | 
| 3 | 
            -
            require  | 
| 4 | 
            -
            require "ds/pair"
         | 
| 3 | 
            +
            require 'ds/pair'
         | 
| 5 4 |  | 
| 6 | 
            -
            require  | 
| 7 | 
            -
            require  | 
| 8 | 
            -
            require  | 
| 5 | 
            +
            require 'ds/arrays/expandable_array'
         | 
| 6 | 
            +
            require 'ds/arrays/array_2d'
         | 
| 7 | 
            +
            require 'ds/arrays/tri_matrix'
         | 
| 8 | 
            +
            require 'ds/arrays/heap_store'
         | 
| 9 9 |  | 
| 10 | 
            -
            require  | 
| 11 | 
            -
             | 
| 12 | 
            -
            require "ds/lists/list_element"
         | 
| 13 | 
            -
            require "ds/lists/list"
         | 
| 14 | 
            -
            require "ds/lists/cyclic_list"
         | 
| 15 | 
            -
            require "ds/lists/ring"
         | 
| 16 | 
            -
             | 
| 17 | 
            -
            require "ds/stacks/stack"
         | 
| 18 | 
            -
            require "ds/queues/queue"
         | 
| 19 | 
            -
            require "ds/queues/priority_queue"
         | 
| 20 | 
            -
             | 
| 21 | 
            -
            require "ds/trees/tree"
         | 
| 22 | 
            -
            require "ds/trees/tree_walker"
         | 
| 23 | 
            -
            require "ds/trees/binary_tree"
         | 
| 24 | 
            -
            require "ds/trees/binary_search_tree"
         | 
| 25 | 
            -
            require "ds/trees/complete_binary_tree"
         | 
| 26 | 
            -
            require "ds/trees/binary_heap"
         | 
| 27 | 
            -
            require "ds/trees/trie"
         | 
| 28 | 
            -
             | 
| 29 | 
            -
            require "ds/graphs/edge"
         | 
| 30 | 
            -
            require "ds/graphs/graph_as_matrix"
         | 
| 31 | 
            -
            require "ds/graphs/graph_as_tri_matrix"
         | 
| 32 | 
            -
            require "ds/graphs/graph"
         | 
| 33 | 
            -
            require "ds/graphs/digraph"
         | 
| 10 | 
            +
            require 'ds/sets/indexed_set'
         | 
| 34 11 |  | 
| 12 | 
            +
            require 'ds/lists/list_element'
         | 
| 13 | 
            +
            require 'ds/lists/list'
         | 
| 35 14 |  | 
| 15 | 
            +
            require 'ds/stacks/stack'
         | 
| 16 | 
            +
            require 'ds/queues/simple_queue'
         | 
| 17 | 
            +
            require 'ds/queues/priority_queue'
         | 
| 36 18 |  | 
| 19 | 
            +
            require 'ds/trees/tree'
         | 
| 20 | 
            +
            require 'ds/trees/tree_walker'
         | 
| 21 | 
            +
            require 'ds/trees/binary_tree'
         | 
| 22 | 
            +
            require 'ds/trees/binary_heap'
         | 
| 23 | 
            +
            require 'ds/trees/red_black_tree'
         | 
| 24 | 
            +
            require 'ds/trees/red_black_tree/node'
         | 
| 25 | 
            +
            require 'ds/trees/trie'
         | 
| 26 | 
            +
            require 'ds/trees/trie/node'
         | 
| @@ -1,17 +1,13 @@ | |
| 1 1 | 
             
            module DS
         | 
| 2 | 
            -
             | 
| 3 | 
            -
              #Implements two dimensional array.  
         | 
| 2 | 
            +
              # Implements two dimensional array.
         | 
| 4 3 | 
             
              class Array2D
         | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
                #Creates new two dimensional array. Init is the default value of the array.
         | 
| 8 | 
            -
                def initialize(size=1,init=0)
         | 
| 4 | 
            +
                # Creates new two dimensional array. Init is the default value of the array.
         | 
| 5 | 
            +
                def initialize(size = 1, init = 0)
         | 
| 9 6 | 
             
                  @init = init
         | 
| 10 | 
            -
                  @store = Array.new(size){Array.new(size){init}}
         | 
| 7 | 
            +
                  @store = Array.new(size) { Array.new(size) { init } }
         | 
| 11 8 | 
             
                end
         | 
| 12 9 |  | 
| 13 | 
            -
                
         | 
| 14 | 
            -
                def [](x,y)
         | 
| 10 | 
            +
                def [](x, y)
         | 
| 15 11 | 
             
                  if @store[x].nil?
         | 
| 16 12 | 
             
                    @store[x] = []
         | 
| 17 13 | 
             
                    @init
         | 
| @@ -22,7 +18,7 @@ module DS | |
| 22 18 | 
             
                  end
         | 
| 23 19 | 
             
                end
         | 
| 24 20 |  | 
| 25 | 
            -
                def []=(x,y,v)
         | 
| 21 | 
            +
                def []=(x, y, v)
         | 
| 26 22 | 
             
                  @store[x] = [] if @store[x].nil?
         | 
| 27 23 | 
             
                  @store[x][y] = v
         | 
| 28 24 | 
             
                end
         | 
| @@ -35,5 +31,8 @@ module DS | |
| 35 31 | 
             
                  @store.flatten
         | 
| 36 32 | 
             
                end
         | 
| 37 33 |  | 
| 34 | 
            +
                def size
         | 
| 35 | 
            +
                  @store.size
         | 
| 36 | 
            +
                end
         | 
| 38 37 | 
             
              end
         | 
| 39 38 | 
             
            end
         | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            module DS
         | 
| 2 | 
            +
              # Class provides access to any element in array. If index i
         | 
| 3 | 
            +
              # is greter than array size then elements from size to i are
         | 
| 4 | 
            +
              # filled with extender.
         | 
| 5 | 
            +
              class ExpandableArray < Array
         | 
| 6 | 
            +
                def initialize(size = 0, extender = 0)
         | 
| 7 | 
            +
                  @extender = extender
         | 
| 8 | 
            +
                  super(size, extender)
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                # Returns element at index. If index is greater than size of array then
         | 
| 12 | 
            +
                # elements from size to index are filled with extender.
         | 
| 13 | 
            +
                def [](x)
         | 
| 14 | 
            +
                  expand(size, x) if x >= size
         | 
| 15 | 
            +
                  super(x)
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                # Sets the element at index. If index is greater than size of array then
         | 
| 19 | 
            +
                # elements from size to index are filled with extender.
         | 
| 20 | 
            +
                def []=(x, v)
         | 
| 21 | 
            +
                  old_size = size
         | 
| 22 | 
            +
                  super(x, v)
         | 
| 23 | 
            +
                  expand(old_size, size - 2) if size - old_size > 1
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                private
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def expand(from, to)
         | 
| 29 | 
            +
                  (from..to).each do |i|
         | 
| 30 | 
            +
                    self[i] = @extender
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
            end
         | 
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            require 'forwardable'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module DS
         | 
| 4 | 
            +
              # Simple Array-like data structure with indexing starting from one.
         | 
| 5 | 
            +
              class HeapStore
         | 
| 6 | 
            +
                extend Forwardable
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def_delegators :@store, :push, :pop, :[], :[]=
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def initialize(*args)
         | 
| 11 | 
            +
                  @store = [nil] + args.to_a
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def length
         | 
| 15 | 
            +
                  @store.size - 1
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                def first
         | 
| 19 | 
            +
                  @store[1]
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                alias size length
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                def empty?
         | 
| 25 | 
            +
                  length <= 0
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def to_a
         | 
| 29 | 
            +
                  @store[1..-1]
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
            end
         | 
| @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            module DS
         | 
| 2 | 
            +
              # Class implements Triangular Matrix (lower).
         | 
| 3 | 
            +
              class TriMatrix
         | 
| 4 | 
            +
                # Creates new triangular matrix.
         | 
| 5 | 
            +
                def initialize(init = 0)
         | 
| 6 | 
            +
                  @store = ExpandableArray.new(0, init)
         | 
| 7 | 
            +
                  @max = 0
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                # Returns element at index x,y (or y,x).
         | 
| 11 | 
            +
                def [](x, y)
         | 
| 12 | 
            +
                  x, y = y, x if y > x
         | 
| 13 | 
            +
                  index = (x * x + x) / 2 + y
         | 
| 14 | 
            +
                  @store[index]
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                # Sets the element at index x,y (or y,x).
         | 
| 18 | 
            +
                def []=(x, y, v)
         | 
| 19 | 
            +
                  x, y = y, x if y > x
         | 
| 20 | 
            +
                  index = (x * x + x) / 2 + y
         | 
| 21 | 
            +
                  @max = x if x > @max
         | 
| 22 | 
            +
                  @store[index] = v
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                def to_a
         | 
| 26 | 
            +
                  @store
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                def size
         | 
| 30 | 
            +
                  @max
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         | 
    
        data/lib/ds/lists/list.rb
    CHANGED
    
    | @@ -1,300 +1,424 @@ | |
| 1 1 | 
             
            module DS
         | 
| 2 | 
            +
              class ListError < StandardError; end
         | 
| 2 3 |  | 
| 3 | 
            -
              #Implements simple list data structure. | 
| 4 | 
            +
              # Implements simple list data structure.
         | 
| 4 5 | 
             
              class List
         | 
| 5 | 
            -
             | 
| 6 6 | 
             
                include Enumerable
         | 
| 7 | 
            +
                include Comparable
         | 
| 7 8 |  | 
| 8 9 | 
             
                attr_accessor :head, :tail
         | 
| 9 10 |  | 
| 10 | 
            -
                #Creates new list. | 
| 11 | 
            -
                def initialize( | 
| 12 | 
            -
                  @ | 
| 13 | 
            -
                  @ | 
| 11 | 
            +
                # Creates new list.
         | 
| 12 | 
            +
                def initialize(*arr)
         | 
| 13 | 
            +
                  @size = 0
         | 
| 14 | 
            +
                  @head = nil
         | 
| 15 | 
            +
                  @tail = nil
         | 
| 16 | 
            +
                  from_array(arr) if arr.any?
         | 
| 14 17 | 
             
                end
         | 
| 15 18 |  | 
| 16 | 
            -
                # | 
| 17 | 
            -
                def  | 
| 18 | 
            -
                  list = new | 
| 19 | 
            -
                   | 
| 20 | 
            -
                  arr.each{ |e| tail = tail.append(e) }
         | 
| 21 | 
            -
                  list.tail = tail
         | 
| 19 | 
            +
                # Clones list
         | 
| 20 | 
            +
                def clone
         | 
| 21 | 
            +
                  list = self.class.new
         | 
| 22 | 
            +
                  each { |e| list.append(e.data) }
         | 
| 22 23 | 
             
                  list
         | 
| 23 24 | 
             
                end
         | 
| 24 25 |  | 
| 25 | 
            -
                # | 
| 26 | 
            +
                # Clears list by reseting head and tail to nil
         | 
| 27 | 
            +
                def clear
         | 
| 28 | 
            +
                  @size = 0
         | 
| 29 | 
            +
                  @head = nil
         | 
| 30 | 
            +
                  @tail = nil
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                # Appends new element to list. Returns list tail
         | 
| 26 34 | 
             
                def append(x)
         | 
| 27 | 
            -
                  last_elem = self.tail
         | 
| 28 35 | 
             
                  if !empty?
         | 
| 29 | 
            -
                    @tail =  | 
| 36 | 
            +
                    @tail = tail.append(x)
         | 
| 37 | 
            +
                    increment_size
         | 
| 30 38 | 
             
                  else
         | 
| 31 | 
            -
                     | 
| 32 | 
            -
                    @tail = @head
         | 
| 39 | 
            +
                    create_first(x)
         | 
| 33 40 | 
             
                  end
         | 
| 41 | 
            +
                  @tail
         | 
| 34 42 | 
             
                end
         | 
| 35 43 |  | 
| 36 | 
            -
                alias  | 
| 44 | 
            +
                alias << append
         | 
| 45 | 
            +
                alias push append
         | 
| 37 46 |  | 
| 38 | 
            -
                #Prepends new element to list.
         | 
| 39 | 
            -
                def  | 
| 47 | 
            +
                # Prepends new element to list. Returns list head
         | 
| 48 | 
            +
                def unshift(x)
         | 
| 40 49 | 
             
                  el = ListElement.new(x)
         | 
| 41 50 | 
             
                  el.next = @head
         | 
| 51 | 
            +
                  @head.prev = el if @head
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                  increment_size
         | 
| 42 54 | 
             
                  @head = el
         | 
| 43 55 | 
             
                end
         | 
| 44 56 |  | 
| 45 | 
            -
                #Removes  | 
| 46 | 
            -
                def  | 
| 47 | 
            -
                   | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
                  else
         | 
| 57 | 
            +
                # Removes list head.
         | 
| 58 | 
            +
                def shift
         | 
| 59 | 
            +
                  raise ListError, 'List already empty' if empty?
         | 
| 60 | 
            +
                  remove(head).data
         | 
| 61 | 
            +
                end
         | 
| 51 62 |  | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 63 | 
            +
                # Return ListElement if it is on list otherwise returns nil
         | 
| 64 | 
            +
                def get(x)
         | 
| 65 | 
            +
                  el = head
         | 
| 66 | 
            +
                  el = el.next while el && el != x
         | 
| 67 | 
            +
                  el
         | 
| 68 | 
            +
                end
         | 
| 57 69 |  | 
| 58 | 
            -
             | 
| 70 | 
            +
                # Return ListElement if it is on list or raises error
         | 
| 71 | 
            +
                def get!(x)
         | 
| 72 | 
            +
                  found = get(x)
         | 
| 73 | 
            +
                  raise ListError, 'Element not found' unless found
         | 
| 74 | 
            +
                end
         | 
| 59 75 |  | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 76 | 
            +
                # Returns list element on given index.
         | 
| 77 | 
            +
                def at(index)
         | 
| 78 | 
            +
                  found = nil
         | 
| 79 | 
            +
                  find_index = lambda do |element, i|
         | 
| 80 | 
            +
                    if i == index
         | 
| 81 | 
            +
                      found = element
         | 
| 82 | 
            +
                      break
         | 
| 83 | 
            +
                    end
         | 
| 62 84 | 
             
                  end
         | 
| 63 | 
            -
                   | 
| 85 | 
            +
                  if index >= 0
         | 
| 86 | 
            +
                    each_with_index(&find_index)
         | 
| 87 | 
            +
                  else
         | 
| 88 | 
            +
                    reverse_each(&find_index)
         | 
| 89 | 
            +
                  end
         | 
| 90 | 
            +
                  found
         | 
| 64 91 | 
             
                end
         | 
| 65 92 |  | 
| 66 | 
            -
                # | 
| 67 | 
            -
                def  | 
| 68 | 
            -
                   | 
| 93 | 
            +
                # Returns list element on given index.
         | 
| 94 | 
            +
                def [](i, count = nil)
         | 
| 95 | 
            +
                  return [] if count && count < 0
         | 
| 96 | 
            +
                  i = (i...i + count) if count && count > 0
         | 
| 97 | 
            +
                  case i
         | 
| 98 | 
            +
                  when Integer
         | 
| 99 | 
            +
                    at(i)
         | 
| 100 | 
            +
                  when Range
         | 
| 101 | 
            +
                    elements_in_range(i)
         | 
| 102 | 
            +
                  end
         | 
| 69 103 | 
             
                end
         | 
| 70 104 |  | 
| 71 | 
            -
                # | 
| 72 | 
            -
                def  | 
| 73 | 
            -
                   | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 76 | 
            -
                   | 
| 77 | 
            -
                     | 
| 105 | 
            +
                # Sets list element on given index.
         | 
| 106 | 
            +
                def []=(i, count = 1, val)
         | 
| 107 | 
            +
                  if i.is_a? Range
         | 
| 108 | 
            +
                    index = i.first
         | 
| 109 | 
            +
                    count = i.size
         | 
| 110 | 
            +
                  else
         | 
| 111 | 
            +
                    index = i
         | 
| 78 112 | 
             
                  end
         | 
| 79 113 |  | 
| 80 | 
            -
                  raise  | 
| 114 | 
            +
                  raise ListError, 'Ivalid count parameter' unless valid_count?(count, index)
         | 
| 81 115 |  | 
| 82 | 
            -
                   | 
| 83 | 
            -
                   | 
| 116 | 
            +
                  el = at(index)
         | 
| 117 | 
            +
                  raise ListError, 'Element not found' unless el
         | 
| 118 | 
            +
                  if val.is_a? Array
         | 
| 119 | 
            +
                    replace(el, List.new(*val), count)
         | 
| 120 | 
            +
                  else
         | 
| 121 | 
            +
                    el.data = val
         | 
| 122 | 
            +
                  end
         | 
| 123 | 
            +
                end
         | 
| 84 124 |  | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 125 | 
            +
                # Replaces list elements with other list
         | 
| 126 | 
            +
                def replace(el, list, count = 1)
         | 
| 127 | 
            +
                  if el.head?
         | 
| 128 | 
            +
                    replace_head(el, list, count)
         | 
| 129 | 
            +
                  elsif el.tail?
         | 
| 130 | 
            +
                    replace_tail(el, list, count)
         | 
| 131 | 
            +
                  else
         | 
| 132 | 
            +
                    replace_inside(el, list, count)
         | 
| 87 133 | 
             
                  end
         | 
| 88 134 | 
             
                end
         | 
| 89 135 |  | 
| 90 | 
            -
                # | 
| 91 | 
            -
                def  | 
| 92 | 
            -
                   | 
| 136 | 
            +
                # Checks if two lists are equal
         | 
| 137 | 
            +
                def <=>(other)
         | 
| 138 | 
            +
                  a = head
         | 
| 139 | 
            +
                  b = other.head
         | 
| 140 | 
            +
                  while a && b && a.data == b.data
         | 
| 141 | 
            +
                    a = a.next
         | 
| 142 | 
            +
                    b = b.next
         | 
| 143 | 
            +
                  end
         | 
| 144 | 
            +
                  compare_list_elements(a, b)
         | 
| 145 | 
            +
                end
         | 
| 93 146 |  | 
| 94 | 
            -
             | 
| 147 | 
            +
                # Appends one list to other
         | 
| 148 | 
            +
                def concat(other)
         | 
| 149 | 
            +
                  other.head.prev = tail
         | 
| 150 | 
            +
                  tail.next = other.head
         | 
| 151 | 
            +
                  self.tail = other.tail
         | 
| 152 | 
            +
                  @size += other.size
         | 
| 153 | 
            +
                  self
         | 
| 154 | 
            +
                end
         | 
| 155 | 
            +
             | 
| 156 | 
            +
                # Inserts element x after another element.
         | 
| 157 | 
            +
                def insert_after(x, rel)
         | 
| 158 | 
            +
                  x = ListElement.new(x)
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                  el = rel
         | 
| 161 | 
            +
                  nxt = el.next
         | 
| 162 | 
            +
                  x.next = nxt
         | 
| 163 | 
            +
                  nxt.prev = x if nxt
         | 
| 164 | 
            +
                  el.next = x
         | 
| 165 | 
            +
                  x.prev = el
         | 
| 166 | 
            +
                  self.tail = x if x.nil?
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                  increment_size
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                  self
         | 
| 171 | 
            +
                end
         | 
| 172 | 
            +
             | 
| 173 | 
            +
                # Inserts element x before another element.
         | 
| 174 | 
            +
                def insert_before(x, rel)
         | 
| 95 175 | 
             
                  if rel == head
         | 
| 96 | 
            -
                    x | 
| 97 | 
            -
             | 
| 176 | 
            +
                    unshift(x)
         | 
| 177 | 
            +
                  else
         | 
| 178 | 
            +
                    x = ListElement.new(x)
         | 
| 179 | 
            +
             | 
| 180 | 
            +
                    prev = rel.prev
         | 
| 181 | 
            +
                    prev.next = x
         | 
| 182 | 
            +
                    x.prev = prev
         | 
| 183 | 
            +
                    x.next = rel
         | 
| 184 | 
            +
                    rel.prev = x
         | 
| 185 | 
            +
                  end
         | 
| 186 | 
            +
                  increment_size
         | 
| 187 | 
            +
                  self
         | 
| 188 | 
            +
                end
         | 
| 98 189 |  | 
| 99 | 
            -
             | 
| 190 | 
            +
                # Removes element x from list.
         | 
| 191 | 
            +
                def remove(x)
         | 
| 192 | 
            +
                  if x == head
         | 
| 193 | 
            +
                    self.head = head.next
         | 
| 194 | 
            +
                    x.next = nil
         | 
| 195 | 
            +
                    head.prev = nil if head
         | 
| 100 196 | 
             
                  else
         | 
| 101 | 
            -
                     | 
| 102 | 
            -
                    prev =  | 
| 103 | 
            -
                     | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
                     | 
| 197 | 
            +
                    nxt = x.next
         | 
| 198 | 
            +
                    prev = x.prev
         | 
| 199 | 
            +
                    prev.next = nxt
         | 
| 200 | 
            +
                    nxt.prev = prev if nxt
         | 
| 201 | 
            +
                    x.next = nil
         | 
| 202 | 
            +
                    x.prev = nil
         | 
| 107 203 |  | 
| 108 | 
            -
                    if  | 
| 109 | 
            -
                      raise ListError, "List element not found"
         | 
| 110 | 
            -
                    else
         | 
| 111 | 
            -
                      prev.next = x
         | 
| 112 | 
            -
                      x.next = el
         | 
| 113 | 
            -
                    end
         | 
| 204 | 
            +
                    self.tail = prev if nxt.nil?
         | 
| 114 205 | 
             
                  end
         | 
| 206 | 
            +
                  decrement_size
         | 
| 207 | 
            +
                  x
         | 
| 115 208 | 
             
                end
         | 
| 116 209 |  | 
| 210 | 
            +
                # Removes last element from list.
         | 
| 211 | 
            +
                def pop
         | 
| 212 | 
            +
                  remove(tail).data
         | 
| 213 | 
            +
                end
         | 
| 117 214 |  | 
| 118 | 
            -
                #Checks if list is empty.
         | 
| 215 | 
            +
                # Checks if list is empty.
         | 
| 119 216 | 
             
                def empty?
         | 
| 120 | 
            -
                   | 
| 217 | 
            +
                  @size.zero?
         | 
| 121 218 | 
             
                end
         | 
| 122 219 |  | 
| 123 | 
            -
                #Returns last element of the list.
         | 
| 220 | 
            +
                # Returns last element of the list.
         | 
| 124 221 | 
             
                def last
         | 
| 125 222 | 
             
                  tail.data
         | 
| 126 223 | 
             
                end
         | 
| 127 224 |  | 
| 225 | 
            +
                # Returns first element of the list.
         | 
| 128 226 | 
             
                def first
         | 
| 129 227 | 
             
                  head.data
         | 
| 130 228 | 
             
                end
         | 
| 131 229 |  | 
| 132 | 
            -
                #Returns length of the list.
         | 
| 230 | 
            +
                # Returns length of the list.
         | 
| 133 231 | 
             
                def length
         | 
| 134 | 
            -
                   | 
| 232 | 
            +
                  @size
         | 
| 135 233 | 
             
                end
         | 
| 136 234 |  | 
| 137 | 
            -
                 | 
| 235 | 
            +
                alias size length
         | 
| 236 | 
            +
             | 
| 237 | 
            +
                # Checks if list is linked at the end with other list.
         | 
| 138 238 | 
             
                def zip?(other)
         | 
| 139 | 
            -
                  tail.equal? other.tail | 
| 239 | 
            +
                  tail.equal? other.tail
         | 
| 140 240 | 
             
                end
         | 
| 141 241 |  | 
| 142 | 
            -
                #Returns joint element if exists, otherwise returns nil.
         | 
| 242 | 
            +
                # Returns joint element if exists, otherwise returns nil.
         | 
| 143 243 | 
             
                def joint
         | 
| 144 244 | 
             
                  elem = head
         | 
| 145 245 | 
             
                  elem2 = elem.next
         | 
| 146 246 |  | 
| 147 | 
            -
                  while elem  | 
| 247 | 
            +
                  while elem && elem2
         | 
| 148 248 |  | 
| 149 | 
            -
                    #traversing by 1
         | 
| 249 | 
            +
                    # traversing by 1
         | 
| 150 250 | 
             
                    elem = elem.next
         | 
| 151 251 |  | 
| 152 | 
            -
                    #traversing by 2
         | 
| 252 | 
            +
                    # traversing by 2
         | 
| 153 253 | 
             
                    elem2 = elem2.next
         | 
| 154 254 | 
             
                    elem2 = elem2.next if elem2
         | 
| 155 255 |  | 
| 156 | 
            -
                    if elem2.equal? elem
         | 
| 157 | 
            -
                      return elem
         | 
| 158 | 
            -
                    end
         | 
| 256 | 
            +
                    return elem if elem2.equal? elem
         | 
| 159 257 | 
             
                  end
         | 
| 160 | 
            -
             | 
| 161 258 | 
             
                  nil
         | 
| 162 259 | 
             
                end
         | 
| 163 260 |  | 
| 164 | 
            -
                #Returns true if list has cycle.
         | 
| 261 | 
            +
                # Returns true if list has cycle.
         | 
| 165 262 | 
             
                def looped?
         | 
| 166 | 
            -
                   | 
| 263 | 
            +
                  !joint.nil?
         | 
| 167 264 | 
             
                end
         | 
| 168 265 |  | 
| 266 | 
            +
                # Returns cycle size or nil if list has no cycles
         | 
| 267 | 
            +
                def cycle_size
         | 
| 268 | 
            +
                  return unless looped?
         | 
| 269 | 
            +
                  counter = 0
         | 
| 270 | 
            +
                  start = joint
         | 
| 271 | 
            +
                  if start
         | 
| 272 | 
            +
                    counter = 1
         | 
| 273 | 
            +
                    elem = start.next
         | 
| 274 | 
            +
                    while elem != start
         | 
| 275 | 
            +
                      elem = elem.next
         | 
| 276 | 
            +
                      counter += 1
         | 
| 277 | 
            +
                    end
         | 
| 278 | 
            +
                  end
         | 
| 279 | 
            +
                  counter
         | 
| 280 | 
            +
                end
         | 
| 169 281 |  | 
| 170 | 
            -
                # | 
| 171 | 
            -
                 | 
| 172 | 
            -
             | 
| 173 | 
            -
             | 
| 174 | 
            -
                   | 
| 175 | 
            -
                   | 
| 176 | 
            -
                   | 
| 282 | 
            +
                # Reverses list.
         | 
| 283 | 
            +
                def reverse!
         | 
| 284 | 
            +
                  @tail = head
         | 
| 285 | 
            +
                  prev = head
         | 
| 286 | 
            +
                  elem = prev.next
         | 
| 287 | 
            +
                  prev.next = nil
         | 
| 288 | 
            +
                  while elem
         | 
| 289 | 
            +
                    nxt = elem.next
         | 
| 290 | 
            +
                    elem.next = prev
         | 
| 291 | 
            +
                    prev.prev = elem
         | 
| 292 | 
            +
                    prev = elem
         | 
| 293 | 
            +
                    elem = nxt
         | 
| 294 | 
            +
                  end
         | 
| 177 295 |  | 
| 178 | 
            -
                   | 
| 296 | 
            +
                  @head = prev
         | 
| 297 | 
            +
                  self
         | 
| 298 | 
            +
                end
         | 
| 179 299 |  | 
| 180 | 
            -
             | 
| 181 | 
            -
             | 
| 182 | 
            -
             | 
| 183 | 
            -
             | 
| 184 | 
            -
                    when 1
         | 
| 185 | 
            -
                      plus_tail = plus.append(el.data)
         | 
| 186 | 
            -
                    when -1
         | 
| 187 | 
            -
                      minus_tail = minus.append(el.data)
         | 
| 188 | 
            -
                    end
         | 
| 300 | 
            +
                # Converts list to array.
         | 
| 301 | 
            +
                def to_a
         | 
| 302 | 
            +
                  map(&:data)
         | 
| 303 | 
            +
                end
         | 
| 189 304 |  | 
| 190 | 
            -
             | 
| 305 | 
            +
                # Default list iterator.
         | 
| 306 | 
            +
                def each
         | 
| 307 | 
            +
                  elem = head
         | 
| 308 | 
            +
                  while elem
         | 
| 309 | 
            +
                    yield elem
         | 
| 310 | 
            +
                    elem = elem.next
         | 
| 191 311 | 
             
                  end
         | 
| 192 | 
            -
             | 
| 193 | 
            -
                  minus_tail.next = zero.head
         | 
| 194 | 
            -
                  zero_tail.next = plus.head
         | 
| 195 | 
            -
                  return minus
         | 
| 196 312 | 
             
                end
         | 
| 197 313 |  | 
| 314 | 
            +
                # Reverse list iterator.
         | 
| 315 | 
            +
                def reverse_each
         | 
| 316 | 
            +
                  elem = tail
         | 
| 317 | 
            +
                  i = 0
         | 
| 318 | 
            +
                  while elem
         | 
| 319 | 
            +
                    i -= 1
         | 
| 320 | 
            +
                    yield elem, i
         | 
| 321 | 
            +
                    elem = elem.prev
         | 
| 322 | 
            +
                  end
         | 
| 323 | 
            +
                end
         | 
| 198 324 |  | 
| 199 | 
            -
                 | 
| 200 | 
            -
             | 
| 201 | 
            -
             | 
| 202 | 
            -
                  b = other.head
         | 
| 325 | 
            +
                def to_s
         | 
| 326 | 
            +
                  to_a.join('=')
         | 
| 327 | 
            +
                end
         | 
| 203 328 |  | 
| 204 | 
            -
             | 
| 329 | 
            +
                private
         | 
| 205 330 |  | 
| 206 | 
            -
             | 
| 207 | 
            -
             | 
| 208 | 
            -
             | 
| 209 | 
            -
             | 
| 331 | 
            +
                def from_array(arr)
         | 
| 332 | 
            +
                  create_first(arr.shift)
         | 
| 333 | 
            +
                  arr.each { |e| append(e) }
         | 
| 334 | 
            +
                end
         | 
| 210 335 |  | 
| 211 | 
            -
             | 
| 212 | 
            -
             | 
| 213 | 
            -
             | 
| 336 | 
            +
                # Creates first element in list.
         | 
| 337 | 
            +
                def create_first(x)
         | 
| 338 | 
            +
                  first = unshift(x)
         | 
| 339 | 
            +
                  self.head = first
         | 
| 340 | 
            +
                  self.tail = first
         | 
| 341 | 
            +
                  self
         | 
| 342 | 
            +
                end
         | 
| 214 343 |  | 
| 215 | 
            -
             | 
| 216 | 
            -
             | 
| 217 | 
            -
             | 
| 218 | 
            -
             | 
| 219 | 
            -
                      self.head = a 
         | 
| 220 | 
            -
                      b = b.next
         | 
| 221 | 
            -
                    else
         | 
| 222 | 
            -
                      a = a.next
         | 
| 223 | 
            -
                      prev.next = a
         | 
| 224 | 
            -
                      b = b.next
         | 
| 225 | 
            -
                    end
         | 
| 344 | 
            +
                def elements_in_range(range)
         | 
| 345 | 
            +
                  arr = []
         | 
| 346 | 
            +
                  each_with_index do |e, i|
         | 
| 347 | 
            +
                    arr << e if range.include?(i)
         | 
| 226 348 | 
             
                  end
         | 
| 227 | 
            -
                   | 
| 349 | 
            +
                  arr
         | 
| 228 350 | 
             
                end
         | 
| 229 351 |  | 
| 230 | 
            -
                 | 
| 231 | 
            -
             | 
| 352 | 
            +
                def increment_size
         | 
| 353 | 
            +
                  @size += 1
         | 
| 354 | 
            +
                end
         | 
| 232 355 |  | 
| 233 | 
            -
             | 
| 234 | 
            -
                   | 
| 356 | 
            +
                def decrement_size
         | 
| 357 | 
            +
                  @size -= 1
         | 
| 358 | 
            +
                end
         | 
| 235 359 |  | 
| 236 | 
            -
             | 
| 237 | 
            -
             | 
| 238 | 
            -
                     | 
| 360 | 
            +
                def compare_list_elements(a, b)
         | 
| 361 | 
            +
                  if a.nil? && b.nil?
         | 
| 362 | 
            +
                    0
         | 
| 363 | 
            +
                  elsif a && b
         | 
| 364 | 
            +
                    a.data <=> b.data
         | 
| 365 | 
            +
                  elsif a.nil?
         | 
| 366 | 
            +
                    -1
         | 
| 239 367 | 
             
                  else
         | 
| 240 | 
            -
                     | 
| 241 | 
            -
                    b = b.next
         | 
| 368 | 
            +
                    1
         | 
| 242 369 | 
             
                  end
         | 
| 370 | 
            +
                end
         | 
| 243 371 |  | 
| 244 | 
            -
             | 
| 245 | 
            -
             | 
| 246 | 
            -
             | 
| 247 | 
            -
                      a = a.next
         | 
| 248 | 
            -
                    else
         | 
| 249 | 
            -
                      result.append(b.data)
         | 
| 250 | 
            -
                      b = b.next
         | 
| 251 | 
            -
                    end
         | 
| 252 | 
            -
                  end
         | 
| 253 | 
            -
                  if !b
         | 
| 254 | 
            -
                    result.tail.next = a
         | 
| 255 | 
            -
                    result.tail = self.tail
         | 
| 256 | 
            -
                  elsif !a
         | 
| 257 | 
            -
                    result.tail.next = b
         | 
| 258 | 
            -
                    result.tail = other.tail
         | 
| 259 | 
            -
                  end
         | 
| 260 | 
            -
                  result
         | 
| 372 | 
            +
                def valid_count?(count, index)
         | 
| 373 | 
            +
                  return true if count.nil?
         | 
| 374 | 
            +
                  !(count < 1 || count + index > size)
         | 
| 261 375 | 
             
                end
         | 
| 262 376 |  | 
| 263 | 
            -
                 | 
| 264 | 
            -
             | 
| 265 | 
            -
             | 
| 266 | 
            -
             | 
| 267 | 
            -
             | 
| 268 | 
            -
                  prev.next = nil
         | 
| 269 | 
            -
                  while elem
         | 
| 270 | 
            -
                    nxt = elem.next
         | 
| 271 | 
            -
                    elem.next = prev
         | 
| 272 | 
            -
                    prev = elem
         | 
| 273 | 
            -
                    elem = nxt
         | 
| 377 | 
            +
                def replace_head(el, list, count)
         | 
| 378 | 
            +
                  count.times do
         | 
| 379 | 
            +
                    temp = el.next
         | 
| 380 | 
            +
                    remove(el)
         | 
| 381 | 
            +
                    el = temp
         | 
| 274 382 | 
             
                  end
         | 
| 275 | 
            -
             | 
| 276 | 
            -
                  @ | 
| 277 | 
            -
                  self
         | 
| 383 | 
            +
                  list.concat self
         | 
| 384 | 
            +
                  @size = list.size
         | 
| 385 | 
            +
                  self.head = list.head
         | 
| 278 386 | 
             
                end
         | 
| 279 387 |  | 
| 280 | 
            -
             | 
| 281 | 
            -
             | 
| 282 | 
            -
             | 
| 283 | 
            -
             | 
| 388 | 
            +
                def replace_tail(el, list, count)
         | 
| 389 | 
            +
                  count.times do
         | 
| 390 | 
            +
                    temp = el.next
         | 
| 391 | 
            +
                    remove(el)
         | 
| 392 | 
            +
                    el = temp
         | 
| 393 | 
            +
                  end
         | 
| 394 | 
            +
                  concat list
         | 
| 284 395 | 
             
                end
         | 
| 285 396 |  | 
| 286 | 
            -
                 | 
| 287 | 
            -
             | 
| 288 | 
            -
                   | 
| 289 | 
            -
                   | 
| 290 | 
            -
                     | 
| 291 | 
            -
             | 
| 397 | 
            +
                def replace_inside(el, list, count)
         | 
| 398 | 
            +
                  first = el
         | 
| 399 | 
            +
                  last = find_last_element(el, count)
         | 
| 400 | 
            +
                  if last.tail?
         | 
| 401 | 
            +
                    self.tail = list.tail
         | 
| 402 | 
            +
                  else
         | 
| 403 | 
            +
                    nxt = last.next
         | 
| 404 | 
            +
                    nxt.prev = list.tail
         | 
| 405 | 
            +
                    list.tail.next = nxt
         | 
| 406 | 
            +
                    last.next = nil
         | 
| 292 407 | 
             
                  end
         | 
| 408 | 
            +
                  prev = first.prev
         | 
| 409 | 
            +
                  list.head.prev = prev
         | 
| 410 | 
            +
                  prev.next = list.head
         | 
| 411 | 
            +
                  first.prev = nil
         | 
| 412 | 
            +
                  @size = @size - count + list.size
         | 
| 293 413 | 
             
                end
         | 
| 294 414 |  | 
| 415 | 
            +
                def find_last_element(el, count)
         | 
| 416 | 
            +
                  last = el
         | 
| 417 | 
            +
                  (count - 1).times do
         | 
| 418 | 
            +
                    temp = last.next if last.next
         | 
| 419 | 
            +
                    last = temp
         | 
| 420 | 
            +
                  end
         | 
| 421 | 
            +
                  last
         | 
| 422 | 
            +
                end
         | 
| 295 423 | 
             
              end
         | 
| 296 | 
            -
             | 
| 297 | 
            -
              class ListError < StandardError
         | 
| 298 | 
            -
              end
         | 
| 299 | 
            -
             | 
| 300 424 | 
             
            end
         |