double_linked_list 0.1.0 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4bd1278ef39c3b852ef5993fbf7dd68da8cf6165
4
- data.tar.gz: c150f49470d1bd86df704fca5a484774a2e73f25
3
+ metadata.gz: 2d32b4473a261613c917ec8481da96bc7eaca8e4
4
+ data.tar.gz: 60e714c5a3baf1318412f3c5817f373ddc0e6d57
5
5
  SHA512:
6
- metadata.gz: 01058c5d4f74e50be1c3e2fb5b569b5bcdf5023686a928161f09e4d9458c5e1ff3f235c5faa4a6fa69e3a52476b5dfa733faf86033b3a72376102ca458a9f365
7
- data.tar.gz: 7f9bb129aa3efeb4b66e9f48e7ddd8569f5c95f918c4f8af678180a8c40ad116931e926f62443b31109f072865da515ce8079eedce62a959c30356db9a943aa0
6
+ metadata.gz: 885e97ebc16d00e86142e1c5bc4ca6a9d4b9e7528be2e7bba8d618b18f2b1a2bb80613a167673a6bccdf56142efceebc6189fb34265a1bd29186108a4201d721
7
+ data.tar.gz: 682228a274f17a1849fc1824ec71a3778f5b93b07739e0878e2ae3af74e996b80e42b0ac3c8fde4f2f932a360d4ed84e9939cc3b404cd3b0df8f26f76192d3fd
data/.travis.yml CHANGED
@@ -1,5 +1,33 @@
1
1
  sudo: false
2
+ cache: bundler
2
3
  language: ruby
3
4
  rvm:
4
- - 2.2.0
5
- before_install: gem install bundler -v 1.12.5
5
+ - 2.1
6
+ - 2.1.6
7
+ - 2.2
8
+ - 2.3.0
9
+ - ruby-head
10
+ - jruby-19mode
11
+ - jruby-9.0.1.0
12
+ - rbx-3
13
+ env:
14
+ # this doesn't do anything for MRI or RBX, but it doesn't hurt them either
15
+ # for JRuby, it enables us to get more accurate coverage data
16
+ - JRUBY_OPTS="--debug"
17
+ matrix:
18
+ allow_failures:
19
+ - rvm: ruby-head
20
+ - rvm: rbx-3
21
+ - rvm: jruby-19mode
22
+ - rvm: jruby-9.0.1.0
23
+ - rvm: 1.9.3
24
+ - rvm: 2.0.0
25
+ fast_finish: true
26
+ before_install: gem update --remote bundler
27
+ install:
28
+ - bundle install --retry=3
29
+ script:
30
+ - bundle exec rspec
31
+ addons:
32
+ code_climate:
33
+ repo_token: 9bc6cf480824676f6f459544eb93d3ad09b4a69e9b42c57c5e657748c38b779a
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in double_linked_list.gemspec
4
4
  gemspec
5
+
6
+ gem 'pry'
data/README.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # DoubleLinkedList
2
2
 
3
+ [![Build Status](https://travis-ci.org/arturictus/double_linked_list.svg?branch=master)](https://travis-ci.org/arturictus/double_linked_list)
4
+ [![Gem Version](https://badge.fury.io/rb/double_linked_list.svg)](https://badge.fury.io/rb/double_linked_list)
5
+ [![Code Climate](https://codeclimate.com/github/arturictus/double_linked_list/badges/gpa.svg)](https://codeclimate.com/github/arturictus/double_linked_list)
6
+ [![Test Coverage](https://codeclimate.com/github/arturictus/double_linked_list/badges/coverage.svg)](https://codeclimate.com/github/arturictus/double_linked_list/coverage)
7
+ [![Issue Count](https://codeclimate.com/github/arturictus/double_linked_list/badges/issue_count.svg)](https://codeclimate.com/github/arturictus/double_linked_list)
8
+
3
9
  The missing Ruby Linked list
4
10
 
5
11
  ## Installation
@@ -39,7 +45,7 @@ llist = DoubleLinkedList.from_a(1, 2, 3)
39
45
  llist.last.datum #=> 3
40
46
  ```
41
47
 
42
- __find:___
48
+ __find:__
43
49
 
44
50
  ```ruby
45
51
  llist = DoubleLinkedList.from_a(1, 2, 3)
@@ -50,13 +56,16 @@ llist.find(3).datum #=> 3
50
56
  llist.find(9) #=> nil
51
57
  ```
52
58
 
53
- __find_previous:__
54
-
59
+ __find_by:__
55
60
  ```ruby
56
- llist = DoubleLinkedList.from_a(1, 2, 3)
57
- llist.find_previous(3).datum #=> 2
58
- llist.find_previous(2).datum #=> 1
59
- llist.find_previous(1) #=> nil
61
+ User = Struct.new(:id)
62
+ users = [
63
+ User.new(1),
64
+ User.new(2),
65
+ User.new(3)
66
+ ]
67
+ llist = DoubleLinkedList.from_a(users)
68
+ llist.find_by{ |elem| elem.datum.id == 1 }.datum.id #=> 1
60
69
  ```
61
70
 
62
71
  __append:__
@@ -69,13 +78,74 @@ llist.last.next #=> be_nil
69
78
  llist.last.previous.datum #=> 3
70
79
  ```
71
80
 
81
+ ## Enumerable
82
+
83
+ - `map`
84
+ - `each`
85
+ - `reverse_each`
86
+
87
+ __each:__
88
+ ```ruby
89
+ DoubleLinkedList.from_a(1, 2, 3).each { |e| puts e.datum }
90
+ # 1
91
+ # 2
92
+ # 3
93
+ ```
94
+
95
+ __map:__
96
+ ```ruby
97
+ DoubleLinkedList.from_a(1, 2, 3).map { |e| e.datum + 1}
98
+ #=> [2, 3, 4]
99
+ ```
100
+
101
+ __reverse_each:__
102
+ ```ruby
103
+ DoubleLinkedList.from_a(1, 2, 3).reverse_each { |e| puts e.datum }
104
+ # 3
105
+ # 2
106
+ # 1
107
+ ```
108
+
109
+ __chunk_by:__
110
+
111
+ It will split the Double linked list in multiple linked list if the block
112
+ returns `truly`.
113
+ The first element of the splitted array are the elememts that return true in the block.
114
+
115
+ ```ruby
116
+ llist = DoubleLinkedList.from_a(1, 2, 3, 4)
117
+ chunked = llist.chunk_by do |e, current_llist|
118
+ e.datum == 3 && current_llist.head.datum == 1
119
+ end
120
+ chunked.first.is_a? DoubleLinkedList #=> true
121
+ chunked.first.head.datum #=> 1
122
+ chunked.first.last.datum #=> 2
123
+ chunked.map{|ll| ll.to_a } #=> [[1, 2], [3, 4]]
124
+ ```
125
+
126
+ __select_by:__
127
+
128
+ For selecting fractions of the linked list avoiding the elements not returned in between the selected head and last sequences.
129
+ In the block must be returned a `DoubleLinkedList::Sequence` instance and head and last in the `DoubleLinkedList::Sequence` must be a `DoubleLinkedList::Element` (the element is passed to the block)
130
+
131
+ ```ruby
132
+ llist = DoubleLinkedList.from_a(1, 2, 3, 4)
133
+ select = llist.select_by do |e|
134
+ if e.datum == 2 && e.next.datum == 3
135
+ DoubleLinkedList::Sequence.new(head: e, last: e.next)
136
+ end
137
+ end
138
+ select.is_a? Array #=> true
139
+ select.first.is_a? DoubleLinkedList #=> true
140
+ select.map{|ll| ll.to_a } #=> [[2, 3]]
141
+ ```
72
142
 
73
143
  ## Development
74
144
 
75
145
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake false ---` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
76
146
 
77
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
147
+ To install this gem onto your local machine, run `bundle exec rake install`. [rubygems.org](https://rubygems.org).
78
148
 
79
149
  ## Contributing
80
150
 
81
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/double_linked_list.
151
+ Bug reports and pull requests are welcome on GitHub at https://github.com/arturictus/double_linked_list.
@@ -21,5 +21,6 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.12"
22
22
  spec.add_development_dependency "rake", "~> 10.0"
23
23
  spec.add_development_dependency "rspec", "~> 3.5"
24
+ spec.add_development_dependency "contextuable"
24
25
  # spec.add_development_dependency "false ---", "~> "
25
26
  end
@@ -0,0 +1,100 @@
1
+ class DoubleLinkedList
2
+ class Element < Struct.new(:datum, :previous, :_next)
3
+ include Enumerable
4
+ alias_method :next, :_next
5
+ alias_method :prev, :previous
6
+
7
+ def each(&block)
8
+ block.call self
9
+ _next.each(&block) if _next
10
+ end
11
+
12
+ def find(datum)
13
+ find_next_by do |elem|
14
+ elem.datum == datum
15
+ end
16
+ end
17
+
18
+ def find_previous_by(&block)
19
+ _finder(:reverse_each, &block)
20
+ end
21
+
22
+ def find_next_by(&block)
23
+ _finder(:each, &block)
24
+ end
25
+
26
+ def reverse_each(&block)
27
+ block.call self
28
+ previous.reverse_each(&block) if previous
29
+ end
30
+
31
+ def append(datum)
32
+ new_last = Element.new(datum, self, nil)
33
+ self._next = new_last
34
+ new_last
35
+ end
36
+
37
+ def chunk_by(acc, &block)
38
+ if acc.empty?
39
+ acc << DoubleLinkedList.from_a(self.datum)
40
+ else
41
+ if block.call(self, acc.last, acc)
42
+ acc << DoubleLinkedList.from_a(self.datum)
43
+ else
44
+ acc.last << self.datum
45
+ end
46
+ end
47
+ _next ? _next.chunk_by(acc, &block) : acc
48
+ end
49
+
50
+ def select_by(acc, &block)
51
+ sequences = []
52
+ find_multiple do |e|
53
+ head_tail = block.call(e)
54
+ if head_tail
55
+ sequences << head_tail
56
+ end
57
+ head_tail
58
+ end
59
+ extract_sequences(sequences)
60
+ end
61
+
62
+ protected
63
+
64
+ def find_multiple(&block)
65
+ found = each_until_found(&block)
66
+ found.next.find_multiple(&block) if found && found.next?
67
+ end
68
+
69
+ def each_until_found(&block)
70
+ found = block.call(self)
71
+ return found if found
72
+ _next.each_until_found(&block) if _next
73
+ end
74
+
75
+ def extract_sequences(sequences)
76
+ sequences.each_with_object([]) do |seq, coll|
77
+ head = seq.head
78
+ head_datum = head.datum
79
+ list = DoubleLinkedList.from_a(head_datum)
80
+ last = nil
81
+ head.find_multiple do |elem|
82
+ next if head_datum == elem.datum
83
+ list << elem.datum
84
+ last = elem.datum if elem.datum == seq.last.datum
85
+ break if last
86
+ end
87
+ coll << list
88
+ end
89
+ end
90
+
91
+ def _finder(direction, &block)
92
+ found = nil
93
+ send(direction) do |elem|
94
+ found = elem if block.call(elem)
95
+ break if found
96
+ end
97
+ found
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,18 @@
1
+ class DoubleLinkedList
2
+ class Sequence
3
+ attr_reader :head, :last
4
+ def initialize(head:, last:)
5
+ @head = head
6
+ @last = last
7
+ end
8
+
9
+ def next
10
+ return unless next?
11
+ last.next
12
+ end
13
+
14
+ def next?
15
+ last.next ? true : false
16
+ end
17
+ end
18
+ end
@@ -1,3 +1,3 @@
1
1
  class DoubleLinkedList
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -3,7 +3,17 @@ require 'forwardable'
3
3
  class DoubleLinkedList
4
4
  extend Forwardable
5
5
  attr_accessor :head, :last
6
- delegate [:datum, :next] => :head
6
+ delegate [
7
+ :datum,
8
+ :next,
9
+ :map,
10
+ :each,
11
+ :reduce,
12
+ ] => :head
13
+
14
+ delegate [
15
+ :reverse_each,
16
+ ] => :last
7
17
 
8
18
  def initialize(datum)
9
19
  @head = (datum.is_a?(Element) ? datum : Element.new(datum))
@@ -11,8 +21,9 @@ class DoubleLinkedList
11
21
 
12
22
  class << self
13
23
  def from_a(*ary)
14
- head = Element.new(ary.first)
15
- last = ary.drop(1).reduce(head) do |cur_last, datum|
24
+ elems = ary.flatten
25
+ head = Element.new(elems.first)
26
+ last = elems.drop(1).reduce(head) do |cur_last, datum|
16
27
  cur_last.append(datum)
17
28
  end
18
29
  new(head).tap do |o|
@@ -24,46 +35,43 @@ class DoubleLinkedList
24
35
  def append(datum)
25
36
  self.last = last.append(datum)
26
37
  end
27
-
38
+ alias_method :<<, :append
28
39
 
29
40
  def find(datum)
30
- found = nil
31
- head.each do |elem|
32
- found = elem if elem.datum == datum
33
- break if found
41
+ find_by do |elem|
42
+ elem.datum == datum
34
43
  end
35
- found
36
44
  end
37
45
 
38
- def find_previous(datum)
39
- found = nil
40
- last.reverse_each do |elem|
41
- found = elem.previous if elem.datum == datum
42
- break if found
46
+ def find_by(&block)
47
+ head.find_next_by(&block)
48
+ end
49
+
50
+ def reverse_find(datum)
51
+ reverse_find_by do |elem|
52
+ elem.datum == datum
43
53
  end
44
- found
45
54
  end
46
55
 
47
- class Element < Struct.new(:datum, :previous, :_next)
48
- include Enumerable
49
- alias_method :next, :_next
50
- alias_method :prev, :previous
56
+ def reverse_find_by(&block)
57
+ last.find_previous_by(&block)
58
+ end
51
59
 
52
- def each(&block)
53
- block.call self
54
- _next.each(&block) if _next
55
- end
60
+ def chunk_by(&block)
61
+ head.chunk_by([], &block)
62
+ end
56
63
 
57
- def each_from_last(&block)
58
- block.call self
59
- previous.each_from_last(&block) if previous
60
- end
61
- alias_method :reverse_each, :each_from_last
64
+ def select_by(&block)
65
+ head.select_by([], &block)
66
+ end
62
67
 
63
- def append(datum)
64
- new_last = Element.new(datum, self, nil)
65
- self._next = new_last
66
- new_last
68
+ def to_a
69
+ [].tap do |ary|
70
+ each{ |elem| ary << elem.datum }
67
71
  end
68
72
  end
73
+
69
74
  end
75
+
76
+ require 'double_linked_list/element'
77
+ require 'double_linked_list/sequence'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: double_linked_list
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Artur Pañach
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-09-01 00:00:00.000000000 Z
11
+ date: 2016-11-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.5'
55
+ - !ruby/object:Gem::Dependency
56
+ name: contextuable
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  description: The missing Ruby Double Linked List.
56
70
  email:
57
71
  - arturictus@gmail.com
@@ -69,6 +83,8 @@ files:
69
83
  - bin/setup
70
84
  - double_linked_list.gemspec
71
85
  - lib/double_linked_list.rb
86
+ - lib/double_linked_list/element.rb
87
+ - lib/double_linked_list/sequence.rb
72
88
  - lib/double_linked_list/version.rb
73
89
  homepage: https://github.com/arturictus/double_linked_list
74
90
  licenses: []
@@ -89,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
89
105
  version: '0'
90
106
  requirements: []
91
107
  rubyforge_project:
92
- rubygems_version: 2.4.5
108
+ rubygems_version: 2.2.3
93
109
  signing_key:
94
110
  specification_version: 4
95
111
  summary: The missing Ruby Double Linked List