double_linked_list 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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