huge_enumerable 0.0.2 → 0.1.1

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
- SHA1:
3
- metadata.gz: bdd8ece0dcce67e7e8af6652859584c88b568715
4
- data.tar.gz: cb41eb56dee65cab7d174e5283dd3d7d06a75e84
2
+ SHA256:
3
+ metadata.gz: a31b89b4c2cdd80273c579549e27b093fa1723f737dcb5dcf67c8609a930ebc9
4
+ data.tar.gz: 8de5ac7d85dd81a51349b763768e3d44dba188590c61802b6fb1d8182a5894c2
5
5
  SHA512:
6
- metadata.gz: 1449cbb6b13a47bc3b1853a8f8cccb0392983e42dc48dc4d596b84e61b71b7e1abb4fb6b6b6454aebe45ffc6a73b0bcb6dded3b5963956a2c50030df226941be
7
- data.tar.gz: 64bdc6abf362ca79c8d4538792c293e81122a23ae95126e60e359edafa05f6e593ff910d440c85325f44f238f162e893afd4c715031d3e3df5b2ec2a5368537f
6
+ metadata.gz: 06d6d73e2c3c2218f0b820a64ee9ee8714cfbdff0350fefcb061b9f965692eab828ec38a1dc159d6b7c38027cb40475525e47491a4adad4dd1770a93919935e6
7
+ data.tar.gz: 4a1e0cbde30ab90bf71c9da8a1d3a180062205ec37e85c21bddbd594401d62ed68c15f4aecb570c60bd5ec385ff14ce0f1ad570adb4b810eb524228c665b4119
@@ -1,4 +1,3 @@
1
- class HugeEnumerable
2
- # "0.0.1"
3
- VERSION = "0.0.2"
4
- end
1
+ class HugeEnumerable
2
+ VERSION = "0.1.1"
3
+ end
@@ -106,11 +106,13 @@ class HugeEnumerable
106
106
  # If no block is given, an HugeCombination is returned instead.
107
107
  # === Caveat
108
108
  # max_array_size is currently inherited by the generated HugeCombination. This may change in the future.
109
- def combination(n) # :yields: element
110
- random_number_generator = rng != self.method(:rand) ? rng : nil
111
- combo = HugeCombination.new(self.dup.reset!, n, max_array_size, random_number_generator)
112
- if block_given?
113
- combo.each { |x| yield x }
109
+ def combination(n, &block) # :yields: element
110
+ # Check to see if we have a specific random number generator to use.
111
+ # Using hash comparison as dups, clones, and other actions can make == and eql? return false when it is actually the same method
112
+ random_number_generator = rng.hash != method(:rand).hash ? rng : nil
113
+ combo = HugeCombination.new(self.clone.reset!, n, max_array_size, random_number_generator)
114
+ if block
115
+ combo.each(&block)
114
116
  self
115
117
  else
116
118
  combo
@@ -118,9 +120,15 @@ class HugeEnumerable
118
120
  end
119
121
 
120
122
  # Calls the given block once for each element in the next array of the collection, passing that element as a parameter.
121
- def each # :yields: element
123
+ def each(&block) # :yields: element
122
124
  # TODO: Return an Enumerator if no block is given
123
- remaining_or(max_array_size).times { |i| yield _fetch(i) }
125
+ remaining_or(max_array_size).times(&(block << method(:_fetch)))
126
+ # remaining_or(max_array_size).times { |i| yield _fetch(i) }
127
+ end
128
+
129
+ def initialize_copy(orig)
130
+ super
131
+ @rng = @rng.unbind.bind(self) if @rng.respond_to?(:unbind) # Make sure this is bound to self if it is a method
124
132
  end
125
133
 
126
134
  def max_array_size #:nodoc:
@@ -142,11 +150,13 @@ class HugeEnumerable
142
150
  # If no block is given, a HugePermutation is returned instead.
143
151
  # === Caveat
144
152
  # max_array_size is currently inherited by the generated HugePermutation. This may change in the future.
145
- def permutation(n) # :yields: element
146
- random_number_generator = rng != self.method(:rand) ? rng : nil
147
- perm = HugePermutation.new(self.dup.reset!, n, max_array_size, random_number_generator)
148
- if block_given?
149
- perm.each { |x| yield x }
153
+ def permutation(n, &block) # :yields: element
154
+ # Check to see if we have a specific random number generator to use.
155
+ # Using hash comparison as dups, clones, and other actions can make == and eql? return false when it is actually the same method
156
+ random_number_generator = rng.hash != method(:rand).hash ? rng : nil
157
+ perm = HugePermutation.new(self.clone.reset!, n, max_array_size, random_number_generator)
158
+ if block
159
+ perm.each(&block)
150
160
  self
151
161
  else
152
162
  perm
@@ -165,12 +175,14 @@ class HugeEnumerable
165
175
  # === Caveat
166
176
  # max_array_size is currently inherited by the generated HugeProduct. This may change in the future.
167
177
  # other_enumerable is duped and reset if it is a HugeEnumerable. This may change in the future.
168
- def product(other_enumerable) # :yields: element
169
- other_enumerable = other_enumerable.dup.reset! if other_enumerable.is_a?(HugeEnumerable)
170
- random_number_generator = rng != self.method(:rand) ? rng : nil
171
- prod = HugeProduct.new(self.dup.reset!, other_enumerable, max_array_size, random_number_generator)
172
- if block_given?
173
- prod.each { |x| yield x }
178
+ def product(other_enumerable, &block) # :yields: element
179
+ other_enumerable = other_enumerable.clone.reset! if other_enumerable.is_a?(HugeEnumerable)
180
+ # Check to see if we have a specific random number generator to use.
181
+ # Using hash comparison as dups, clones, and other actions can make == and eql? return false when it is actually the same method
182
+ random_number_generator = rng.hash != method(:rand).hash ? rng : nil
183
+ prod = HugeProduct.new(self.clone.reset!, other_enumerable, max_array_size, random_number_generator)
184
+ if block
185
+ prod.each(&block)
174
186
  self
175
187
  else
176
188
  prod
@@ -221,7 +233,7 @@ class HugeEnumerable
221
233
  # ==== Side Effects
222
234
  # The new collection is reset to the current collection's original size and elements before shuffling.
223
235
  def shuffle(rng=nil)
224
- self.dup.shuffle!(rng)
236
+ self.clone.shuffle!(rng)
225
237
  end
226
238
 
227
239
  # Randomly reorders the elements of the collection.
metadata CHANGED
@@ -1,99 +1,91 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: huge_enumerable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Frank Hall
8
- autorequire:
9
- bindir: bin
8
+ autorequire:
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2013-06-25 00:00:00.000000000 Z
11
+ date: 2024-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: prime_miller_rabin
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.3'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ~>
19
+ version: '0.1'
20
+ - - ">="
25
21
  - !ruby/object:Gem::Version
26
- version: '1.3'
27
- - !ruby/object:Gem::Dependency
28
- name: rake
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - '>='
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
22
+ version: 0.1.0
23
+ type: :runtime
35
24
  prerelease: false
36
25
  version_requirements: !ruby/object:Gem::Requirement
37
26
  requirements:
38
- - - '>='
27
+ - - "~>"
39
28
  - !ruby/object:Gem::Version
40
- version: '0'
29
+ version: '0.1'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.1.0
41
33
  - !ruby/object:Gem::Dependency
42
- name: rspec
34
+ name: bundler
43
35
  requirement: !ruby/object:Gem::Requirement
44
36
  requirements:
45
- - - ~>
37
+ - - "~>"
46
38
  - !ruby/object:Gem::Version
47
- version: '2.13'
39
+ version: '2.3'
48
40
  type: :development
49
41
  prerelease: false
50
42
  version_requirements: !ruby/object:Gem::Requirement
51
43
  requirements:
52
- - - ~>
44
+ - - "~>"
53
45
  - !ruby/object:Gem::Version
54
- version: '2.13'
46
+ version: '2.3'
55
47
  - !ruby/object:Gem::Dependency
56
- name: rdoc
48
+ name: rake
57
49
  requirement: !ruby/object:Gem::Requirement
58
50
  requirements:
59
- - - '>='
51
+ - - "~>"
60
52
  - !ruby/object:Gem::Version
61
- version: '0'
53
+ version: '13'
62
54
  type: :development
63
55
  prerelease: false
64
56
  version_requirements: !ruby/object:Gem::Requirement
65
57
  requirements:
66
- - - '>='
58
+ - - "~>"
67
59
  - !ruby/object:Gem::Version
68
- version: '0'
60
+ version: '13'
69
61
  - !ruby/object:Gem::Dependency
70
- name: backports
62
+ name: rspec
71
63
  requirement: !ruby/object:Gem::Requirement
72
64
  requirements:
73
- - - '>='
65
+ - - "~>"
74
66
  - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :runtime
67
+ version: '3'
68
+ type: :development
77
69
  prerelease: false
78
70
  version_requirements: !ruby/object:Gem::Requirement
79
71
  requirements:
80
- - - '>='
72
+ - - "~>"
81
73
  - !ruby/object:Gem::Version
82
- version: '0'
74
+ version: '3'
83
75
  - !ruby/object:Gem::Dependency
84
- name: prime_miller_rabin
76
+ name: rdoc
85
77
  requirement: !ruby/object:Gem::Requirement
86
78
  requirements:
87
- - - '>='
79
+ - - "~>"
88
80
  - !ruby/object:Gem::Version
89
- version: 0.0.2
90
- type: :runtime
81
+ version: '6.4'
82
+ type: :development
91
83
  prerelease: false
92
84
  version_requirements: !ruby/object:Gem::Requirement
93
85
  requirements:
94
- - - '>='
86
+ - - "~>"
95
87
  - !ruby/object:Gem::Version
96
- version: 0.0.2
88
+ version: '6.4'
97
89
  description: Enumerate, sample, shuffle, combine, permutate, and create products of
98
90
  massive data sets using minimal memory
99
91
  email:
@@ -102,53 +94,40 @@ executables: []
102
94
  extensions: []
103
95
  extra_rdoc_files: []
104
96
  files:
105
- - .gitignore
106
97
  - Gemfile
107
98
  - LICENSE.txt
108
99
  - README.md
109
100
  - Rakefile
110
- - huge_enumerable.gemspec
111
101
  - lib/huge_enumerable.rb
112
102
  - lib/huge_enumerable/huge_collection.rb
113
103
  - lib/huge_enumerable/huge_combination.rb
114
104
  - lib/huge_enumerable/huge_permutation.rb
115
105
  - lib/huge_enumerable/huge_product.rb
116
106
  - lib/huge_enumerable/version.rb
117
- - spec/lib/huge_enumerable/huge_collection_spec.rb
118
- - spec/lib/huge_enumerable/huge_combination_spec.rb
119
- - spec/lib/huge_enumerable/huge_permutation_spec.rb
120
- - spec/lib/huge_enumerable/huge_product_spec.rb
121
- - spec/lib/huge_enumerable_spec.rb
122
- - spec/spec_helper.rb
123
- homepage: https://github.com/ChapterHouse/huge_enumerable.git
107
+ homepage: https://github.com/ChapterHouse/huge_enumerable
124
108
  licenses:
125
109
  - MIT
126
- metadata: {}
127
- post_install_message:
110
+ metadata:
111
+ homepage_uri: https://github.com/ChapterHouse/huge_enumerable
112
+ source_code_uri: https://github.com/ChapterHouse/huge_enumerable/tree/v0.1.1
113
+ post_install_message:
128
114
  rdoc_options: []
129
115
  require_paths:
130
116
  - lib
131
117
  required_ruby_version: !ruby/object:Gem::Requirement
132
118
  requirements:
133
- - - '>='
119
+ - - ">="
134
120
  - !ruby/object:Gem::Version
135
- version: '0'
121
+ version: 3.0.0
136
122
  required_rubygems_version: !ruby/object:Gem::Requirement
137
123
  requirements:
138
- - - '>='
124
+ - - ">="
139
125
  - !ruby/object:Gem::Version
140
126
  version: '0'
141
127
  requirements: []
142
- rubyforge_project:
143
- rubygems_version: 2.0.2
144
- signing_key:
128
+ rubygems_version: 3.2.33
129
+ signing_key:
145
130
  specification_version: 4
146
131
  summary: Enumerate, sample, shuffle, combine, permutate, and create products of massive
147
132
  data sets using minimal memory
148
- test_files:
149
- - spec/lib/huge_enumerable/huge_collection_spec.rb
150
- - spec/lib/huge_enumerable/huge_combination_spec.rb
151
- - spec/lib/huge_enumerable/huge_permutation_spec.rb
152
- - spec/lib/huge_enumerable/huge_product_spec.rb
153
- - spec/lib/huge_enumerable_spec.rb
154
- - spec/spec_helper.rb
133
+ test_files: []
data/.gitignore DELETED
@@ -1,21 +0,0 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- Gemfile.lock
6
- InstalledFiles
7
- coverage
8
- InstalledFiles
9
- lib/bundler/man
10
- pkg
11
- rdoc
12
- spec/reports
13
- test/tmp
14
- test/version_tmp
15
- tmp
16
-
17
- # YARD artifacts
18
- .yardoc
19
- _yardoc
20
- doc/
21
- .idea
@@ -1,28 +0,0 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'huge_enumerable/version'
5
-
6
- Gem::Specification.new do |spec|
7
- spec.name = "huge_enumerable"
8
- spec.version = HugeEnumerable::VERSION
9
- spec.authors = ["Frank Hall"]
10
- spec.email = ["ChapterHouse.Dune@gmail.com"]
11
- spec.description = %q{Enumerate, sample, shuffle, combine, permutate, and create products of massive data sets using minimal memory}
12
- spec.summary = %q{Enumerate, sample, shuffle, combine, permutate, and create products of massive data sets using minimal memory}
13
- spec.homepage = "https://github.com/ChapterHouse/huge_enumerable.git"
14
- spec.license = "MIT"
15
-
16
- spec.files = `git ls-files`.split($/)
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
20
-
21
- spec.add_development_dependency "bundler", "~> 1.3"
22
- spec.add_development_dependency "rake"
23
- spec.add_development_dependency 'rspec', '~> 2.13'
24
- spec.add_development_dependency 'rdoc'
25
- spec.add_runtime_dependency "backports" # Wish this could be conditional. It is only used for ruby 1.8 for as long as I support it.
26
- spec.add_runtime_dependency "prime_miller_rabin", ">= 0.0.2"
27
-
28
- end
@@ -1,33 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe HugeCollection do
4
-
5
- let(:enumerable) { ('a'..'z').to_a }
6
-
7
- subject(:collection) do
8
- HugeCollection.send(:public, :collection_size)
9
- HugeCollection.send(:public, :fetch)
10
- HugeCollection.new(enumerable)
11
- end
12
-
13
- context "#collection_size" do
14
-
15
- it "is equal to the original enumerable size" do
16
- collection.collection_size.should eql(enumerable.size)
17
- end
18
-
19
- end
20
-
21
- context "#fetch" do
22
-
23
- it "returns values in the same order as enumerable[]" do
24
- enumerable_fetches = []
25
- collection_fetches = []
26
- enumerable.size.times { |i| enumerable_fetches << enumerable[i] }
27
- collection.collection_size.times { |i| collection_fetches << collection.fetch(i) }
28
- collection_fetches.should eql(enumerable_fetches)
29
- end
30
-
31
- end
32
-
33
- end
@@ -1,39 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe HugeCombination do
4
-
5
- let(:enumerable) { ('a'..'z').to_a }
6
- let(:combination_size) { 3 }
7
-
8
- subject(:combination) do
9
- HugeCombination.send(:public, :collection_size)
10
- HugeCombination.send(:public, :fetch)
11
- HugeCombination.new(enumerable, combination_size)
12
- end
13
-
14
- def enum_combo(x)
15
- @cache ||= {}
16
- @cache[x.to_i] ||= enumerable.combination(x).to_a
17
- end
18
-
19
- context "#collection_size" do
20
-
21
- it "is equal to array#combination.to_a.size" do
22
- combination.collection_size.should eql(enum_combo(combination_size).size)
23
- end
24
-
25
- end
26
-
27
- context "#fetch" do
28
-
29
- it "returns values in the same order as array#combination.to_a[]" do
30
- enum_combo_fetches = []
31
- combination_fetches = []
32
- enum_combo(combination_size).size.times { |i| enum_combo_fetches << enum_combo(combination_size)[i] }
33
- combination.collection_size.times { |i| combination_fetches << combination.fetch(i) }
34
- combination_fetches.should eql(enum_combo_fetches)
35
- end
36
-
37
- end
38
-
39
- end
@@ -1,39 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe HugePermutation do
4
-
5
- let(:enumerable) { ('a'..'z').to_a }
6
- let(:permutation_size) { 3 }
7
-
8
- subject(:permutation) do
9
- HugePermutation.send(:public, :collection_size)
10
- HugePermutation.send(:public, :fetch)
11
- HugePermutation.new(enumerable, permutation_size)
12
- end
13
-
14
- def enum_perm(x)
15
- @cache ||= {}
16
- @cache[x.to_i] ||= enumerable.permutation(x).to_a
17
- end
18
-
19
- context "#collection_size" do
20
-
21
- it "is equal to array#permutation.to_a.size" do
22
- permutation.collection_size.should eql(enum_perm(permutation_size).size)
23
- end
24
-
25
- end
26
-
27
- context "#fetch" do
28
-
29
- it "returns values in the same order as array#permutation.to_a[]" do
30
- enum_perm_fetches = []
31
- permutation_fetches = []
32
- enum_perm(permutation_size).size.times { |i| enum_perm_fetches << enum_perm(permutation_size)[i] }
33
- permutation.collection_size.times { |i| permutation_fetches << permutation.fetch(i) }
34
- permutation_fetches.should eql(enum_perm_fetches)
35
- end
36
-
37
- end
38
-
39
- end
@@ -1,35 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe HugeProduct do
4
-
5
- let(:enumerable_a) { ('a'..'z').to_a }
6
- let(:enumerable_b) { ('A'..'Z').to_a }
7
- let(:enum_prod) { enumerable_a.product(enumerable_b) }
8
-
9
- subject(:product) do
10
- HugeProduct.send(:public, :collection_size)
11
- HugeProduct.send(:public, :fetch)
12
- HugeProduct.new(enumerable_a, enumerable_b)
13
- end
14
-
15
- context "#collection_size" do
16
-
17
- it "is equal to array#product(other_ary).size" do
18
- product.collection_size.should eql(enum_prod.size)
19
- end
20
-
21
- end
22
-
23
- context "#fetch" do
24
-
25
- it "returns values in the same order as array#product(other_ary)[]" do
26
- enum_prod_fetches = []
27
- product_fetches = []
28
- enum_prod.size.times { |i| enum_prod_fetches << enum_prod[i] }
29
- product.collection_size.times { |i| product_fetches << product.fetch(i) }
30
- product_fetches.should eql(enum_prod_fetches)
31
- end
32
-
33
- end
34
-
35
- end
@@ -1,642 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe HugeEnumerable do
4
-
5
- let(:collection) { ('a'..'z').to_a }
6
-
7
- subject(:enumerable) do
8
- klass = Class.new(HugeEnumerable)
9
- enum_collection = collection.sort
10
- klass.send(:define_method, :collection_size) { enum_collection.size }
11
- klass.send(:define_method, :fetch) { |x| enum_collection[x] }
12
- klass.send(:public, :next_prime)
13
- klass.send(:public, :_fetch)
14
- klass.send(:public, :element_or_array)
15
- klass.send(:public, :full_cycle_increment)
16
- klass.new
17
- end
18
-
19
- subject(:emptied_enumerable) do
20
- enumerable.tap do |enum|
21
- enum.max_array_size = enum.size
22
- enum.next_array
23
- end
24
- end
25
-
26
- context ".new" do
27
-
28
- context "with no arguments" do
29
-
30
- it "defaults max_array_size to a Numeric" do
31
- enumerable.max_array_size.should be_kind_of(Numeric)
32
- end
33
-
34
- it "defaults rng to #rand" do
35
- enumerable.rng.should eq(enumerable.method(:rand))
36
- end
37
-
38
- end
39
-
40
- end
41
-
42
- context "#[]" do
43
-
44
- context "with a positive index" do
45
- it "returns the element from the beginning of the collection at the specified index" do
46
- enumerable[3].should eql(collection[3])
47
- end
48
- end
49
-
50
- context "with a negative index" do
51
- it "returns the element from the end of the collection at the specified index" do
52
- enumerable[-3].should eql(collection[-3])
53
- end
54
- end
55
-
56
- context "with an out of bounds index" do
57
- it "returns nil" do
58
- enumerable[enumerable.size + 1].should be_nil
59
- end
60
- end
61
-
62
- context "with a range" do
63
- it "returns an array of elements corresponding to indexes within the range" do
64
- size = collection.size + 1
65
- test_range = (-size..size).to_a
66
- ranges = test_range.product(test_range).map { |x| (x.first..x.last) }
67
- arrays = ranges.map { |range| [enumerable[range], collection[range]] }
68
- arrays.each { |x| x.first.should eq(x.last) }
69
- end
70
- end
71
-
72
- context "with a length" do
73
- it "returns an array of elements corresponding to starting with index and containing a maximum of length items" do
74
- size = collection.size + 1
75
- test_range = (-size..size).to_a
76
- index_lengths = test_range.product(test_range).map { |x| [x.first, x.last] }
77
- arrays = index_lengths.map do |idx_len|
78
- index = idx_len.first
79
- length = idx_len.last
80
- [enumerable[index, length], collection[index, length]]
81
- end
82
- arrays.each { |x| x.first.should eq(x.last) }
83
- end
84
- end
85
-
86
-
87
- it "relays to #_fetch for index mapping" do
88
- enumerable.should_receive(:_fetch).at_least(:once)
89
- enumerable[0]
90
- end
91
-
92
- end
93
-
94
- context "#each" do
95
-
96
- it "yields #max_array_size items" do
97
- items = []
98
- total_items = collection.size / 5
99
- enumerable.max_array_size = total_items
100
- enumerable.each { |x| items << x }
101
- items.size.should eql(total_items)
102
- end
103
-
104
- it "yields only the remaining items if there are fewer than #max_array_size" do
105
- items = []
106
- enumerable.max_array_size = collection.size + 1
107
- enumerable.each { |x| items << x }
108
- items.size.should eql(collection.size)
109
- end
110
-
111
- it "relays to #_fetch for index mapping" do
112
- enumerable.should_receive(:_fetch).at_least(:once)
113
- enumerable.each {}
114
- end
115
-
116
- end
117
-
118
- context "#combination" do
119
-
120
- context "with no block" do
121
-
122
- it "returns a new HugeCombination" do
123
- enumerable.combination(2).should be_instance_of(HugeCombination)
124
- end
125
-
126
- end
127
-
128
- context "with a block" do
129
-
130
- # This should really be calls the block from the combination since there is testing duplication here.
131
- # However, knowing where the block is called from would need stack investigation or similar.
132
- it "calls the block for each combination element" do
133
- combo = enumerable.combination(2)
134
- enumerable.max_array_size = combo.size # Hrm. Perhaps having to do this is a reason to have it call collection_each
135
- index = 0
136
- enumerable.combination(2) do |x|
137
- x.should eql(combo[index])
138
- index += 1
139
- end
140
- index.should eql(combo.size)
141
- end
142
-
143
- it "returns self" do
144
- enumerable.combination(2) {}.should equal(enumerable)
145
- end
146
-
147
- end
148
-
149
- it "uses self a dup of itself as the enumerable" do
150
- dupped_enumerable = enumerable.dup
151
- enumerable.stub(:dup).and_return(dupped_enumerable)
152
- HugeCombination.should_receive(:new).with(dupped_enumerable, 2, enumerable.max_array_size, nil)
153
- enumerable.combination(2)
154
- end
155
-
156
- it "uses the same max array size" do
157
- enumerable.combination(2).max_array_size.should eql(enumerable.max_array_size)
158
- end
159
-
160
- it "uses the same random number generator" do
161
- enumerable.rng = Proc.new { 1 }
162
- enumerable.combination(2).rng.should eq(enumerable.rng)
163
- end
164
-
165
- it "calls reset! on the dup" do
166
- HugeEnumerable.send(:public, :reset!)
167
- dupped_enumerable = enumerable.dup
168
- enumerable.stub(:dup).and_return(dupped_enumerable)
169
- dupped_enumerable.should_receive(:reset!).and_call_original
170
- enumerable.combination(2)
171
- end
172
-
173
- end
174
-
175
-
176
- context "#max_array_size" do
177
-
178
- context "not explicitly set" do
179
-
180
- it "defaults to DEFAULT_MAX_ARRAY_SIZE if smaller than #collection_size" do
181
- enumerable.stub(:collection_size).and_return(HugeEnumerable::DEFAULT_MAX_ARRAY_SIZE + 1)
182
- enumerable.max_array_size.should eql(HugeEnumerable::DEFAULT_MAX_ARRAY_SIZE)
183
- end
184
-
185
- it "defaults to #collection_size if smaller than DEFAULT_MAX_ARRAY_SIZE" do
186
- enumerable.stub(:collection_size).and_return(HugeEnumerable::DEFAULT_MAX_ARRAY_SIZE - 1)
187
- enumerable.max_array_size.should eql(HugeEnumerable::DEFAULT_MAX_ARRAY_SIZE - 1)
188
- end
189
-
190
- end
191
-
192
- end
193
-
194
- context "#next_array" do
195
-
196
- it "advances to the next array in the collection" do
197
- size = collection.size / 5
198
- enumerable.max_array_size = size
199
- enumerable.next_array.should eql(collection[size...size*2])
200
- end
201
-
202
- it "changes #size" do
203
- size = collection.size / 5
204
- enumerable.max_array_size = size
205
- enumerable.next_array
206
- enumerable.size.should eql(collection.size - size)
207
- end
208
-
209
- end
210
-
211
- context "#empty?" do
212
-
213
- it "returns true if the collection has been entirely emptied by #pop, #shift, or #next_array" do
214
- enumerable.max_array_size = collection.size
215
- enumerable.next_array
216
- enumerable.empty?.should be_true
217
- end
218
-
219
- it "returns false if the collection has been not entirely emptied by #pop, #shift, or #next_array" do
220
- enumerable.max_array_size = collection.size - 1
221
- enumerable.next_array
222
- enumerable.empty?.should be_false
223
- end
224
-
225
- end
226
-
227
- context "#permutation" do
228
-
229
- context "with no block" do
230
-
231
- it "returns a new HugePermutation" do
232
- enumerable.permutation(2).should be_instance_of(HugePermutation)
233
- end
234
-
235
- end
236
-
237
- context "with a block" do
238
-
239
- # This should really be calls the block from the combination since there is testing duplication here.
240
- # However, knowing where the block is called from would need stack investigation or similar.
241
- it "calls the block for each permutation element" do
242
- perm = enumerable.permutation(2)
243
- enumerable.max_array_size = perm.size # Hrm. Perhaps having to do this is a reason to have it call collection_each
244
- index = 0
245
- enumerable.permutation(2) do |x|
246
- x.should eql(perm[index])
247
- index += 1
248
- end
249
- index.should eql(perm.size)
250
- end
251
-
252
- it "returns self" do
253
- enumerable.permutation(2) {}.should equal(enumerable)
254
- end
255
-
256
- end
257
-
258
- it "uses self a dup of itself as the enumerable" do
259
- dupped_enumerable = enumerable.dup
260
- enumerable.stub(:dup).and_return(dupped_enumerable)
261
- HugePermutation.should_receive(:new).with(dupped_enumerable, 2, enumerable.max_array_size, nil)
262
- enumerable.permutation(2)
263
- end
264
-
265
- it "uses the same max array size" do
266
- enumerable.permutation(2).max_array_size.should eql(enumerable.max_array_size)
267
- end
268
-
269
- it "uses the same random number generator" do
270
- enumerable.rng = Proc.new { 1 }
271
- enumerable.permutation(2).rng.should eq(enumerable.rng)
272
- end
273
-
274
- it "calls reset! on the dup" do
275
- HugeEnumerable.send(:public, :reset!)
276
- dupped_enumerable = enumerable.dup
277
- enumerable.stub(:dup).and_return(dupped_enumerable)
278
- dupped_enumerable.should_receive(:reset!).and_call_original
279
- enumerable.permutation(2)
280
- end
281
-
282
- end
283
-
284
-
285
- context "#pop" do
286
-
287
- context "on a non empty collection" do
288
- context "with no parameter" do
289
- it "returns the next element from the end of the collection" do
290
- enumerable.pop.should eql(collection.pop)
291
- end
292
- end
293
-
294
- context "with a parameter" do
295
- it "returns an array of the next N elements from the end of the collection" do
296
- enumerable.pop(3).should eql(collection.pop(3))
297
- end
298
- end
299
-
300
- it "removes the elements from the end of the collection" do
301
- enumerable.pop
302
- enumerable.pop(3)
303
- enumerable.to_a.should eql(collection[0..-5])
304
- end
305
-
306
- it "changes #size" do
307
- enumerable.pop
308
- enumerable.pop(3)
309
- enumerable.size.should eql(collection.size - 4)
310
- end
311
-
312
- it "does not harm the original collection" do
313
- original = collection.dup
314
- enumerable.pop
315
- enumerable.pop(3)
316
- collection.should eql(original)
317
- end
318
-
319
- end
320
-
321
- it "depends on #(private)element_or_array" do
322
- enumerable.should_receive(:element_or_array).twice.and_call_original
323
- enumerable.pop
324
- enumerable.pop(3)
325
- end
326
-
327
- end
328
-
329
- context "#product" do
330
-
331
- context "with no block" do
332
-
333
- it "returns a new HugeProduct" do
334
- enumerable.product([]).should be_instance_of(HugeProduct)
335
- end
336
-
337
- end
338
-
339
- context "with a block" do
340
-
341
- # This should really be calls the block from the combination since there is testing duplication here.
342
- # However, knowing where the block is called from would need stack investigation or similar.
343
- it "calls the block for each product element" do
344
- other_enumerable = [1, 2, 3]
345
- prod = enumerable.product(other_enumerable)
346
- enumerable.max_array_size = prod.size # Hrm. Perhaps having to do this is a reason to have it call collection_each
347
- index = 0
348
- enumerable.product(other_enumerable) do |x|
349
- x.should eql(prod[index])
350
- index += 1
351
- end
352
- index.should eql(prod.size)
353
- end
354
-
355
- it "returns self" do
356
- enumerable.product([]) {}.should equal(enumerable)
357
- end
358
-
359
- end
360
-
361
- it "uses self a dup of itself as the enumerable" do
362
- dupped_enumerable = enumerable.dup
363
- enumerable.stub(:dup).and_return(dupped_enumerable)
364
- other_enumerable = []
365
- HugeProduct.should_receive(:new).with(dupped_enumerable, other_enumerable, enumerable.max_array_size, nil)
366
- enumerable.product(other_enumerable)
367
- end
368
-
369
- it "calls dup on the other enumerable if it is a HugeEnumerable" do
370
- other_enumerable = HugeCollection.new([])
371
- other_enumerable.should_receive(:dup).and_call_original
372
- enumerable.product(other_enumerable)
373
- end
374
-
375
- it "calls reset on the other enumerable if it is a HugeEnumerable" do
376
- HugeEnumerable.send(:public, :reset!)
377
- other_enumerable = HugeCollection.new([])
378
- dupped_enumerable = other_enumerable.dup
379
- other_enumerable.stub(:dup).and_return(dupped_enumerable)
380
- dupped_enumerable.should_receive(:reset!).and_call_original
381
- enumerable.product(other_enumerable)
382
- end
383
-
384
- it "does not call dup on the other enumerable if it is a HugeEnumerable" do
385
- other_enumerable = []
386
- other_enumerable.should_not_receive(:dup)
387
- enumerable.product(other_enumerable)
388
- end
389
-
390
- it "uses the same max array size" do
391
- enumerable.product([]).max_array_size.should eql(enumerable.max_array_size)
392
- end
393
-
394
- it "uses the same random number generator" do
395
- enumerable.rng = Proc.new { 1 }
396
- enumerable.product([]).rng.should eq(enumerable.rng)
397
- end
398
-
399
- it "calls reset! on the dup" do
400
- HugeEnumerable.send(:public, :reset!)
401
- dupped_enumerable = enumerable.dup
402
- enumerable.stub(:dup).and_return(dupped_enumerable)
403
- dupped_enumerable.should_receive(:reset!).and_call_original
404
- enumerable.product([])
405
- end
406
-
407
- end
408
-
409
- context "#sample" do
410
-
411
- context "on an non empty collection" do
412
- context "with no arguments" do
413
- it "returns a single element from the collection" do
414
- collection.include?(enumerable.sample).should be_true
415
- end
416
- end
417
-
418
- context "with size argument" do
419
- it "returns N elements from the collection" do
420
- samples = enumerable.sample(3)
421
- samples.should have(3).items
422
- samples.all? { |item| collection.include?(item) }.should be_true
423
- end
424
- end
425
-
426
- it "returns elements from the collection in a pseudo random pattern" do
427
- enumerable.sample(enumerable.size).should_not eq(collection)
428
- end
429
-
430
- it "visits each element exactly once before repeating" do
431
- samples = []
432
- enumerable.size.times { samples << enumerable.sample }
433
- samples.uniq.should have(collection.size).items
434
- end
435
-
436
- it "does not reorder the original collection" do
437
- original = collection.dup
438
- enumerable.sample
439
- enumerable.sample(3)
440
- collection.should eql(original)
441
- end
442
-
443
- end
444
-
445
- it "depends on #(private)element_or_array" do
446
- enumerable.should_receive(:element_or_array).twice.and_call_original
447
- enumerable.sample
448
- enumerable.sample(3)
449
- end
450
-
451
- end
452
-
453
- context "#shift" do
454
-
455
- context "on a non empty collection" do
456
- context "with no parameter" do
457
- it "returns the next element from the beginning of the collection" do
458
- enumerable.shift.should eql(collection.shift)
459
- end
460
- end
461
-
462
- context "with a parameter" do
463
- it "returns an array of the next N elements from the beginning of the collection" do
464
- enumerable.shift(3).should eql(collection.shift(3))
465
- end
466
- end
467
-
468
- it "removes the elements from the beginning of the collection" do
469
- enumerable.shift
470
- enumerable.shift(3)
471
- enumerable.to_a.should eql(collection[4..-1])
472
- end
473
-
474
- it "changes #size" do
475
- enumerable.shift
476
- enumerable.shift(3)
477
- enumerable.size.should eql(collection.size - 4)
478
- end
479
-
480
- it "does not harm the original collection" do
481
- original = collection.dup
482
- enumerable.shift
483
- enumerable.shift(3)
484
- collection.should eql(original)
485
- end
486
-
487
- end
488
-
489
- it "depends on #(private)element_or_array" do
490
- enumerable.should_receive(:element_or_array).twice.and_call_original
491
- enumerable.shift
492
- enumerable.shift(3)
493
- end
494
-
495
- end
496
-
497
- context "#shuffle" do
498
-
499
- it "returns a new HugeEnumerable" do
500
- enumerable.shuffle.should_not equal(enumerable)
501
- end
502
-
503
- end
504
-
505
- context "#shuffle!" do
506
-
507
- it "randomly alters the order of the sequence" do
508
- fake_random = Proc.new { |x| 2 % x }
509
- enumerable.max_array_size = enumerable.size
510
- original = enumerable.to_a
511
- enumerable.shuffle!(fake_random)
512
- shuffle1 = enumerable.to_a
513
- fake_random = Proc.new { |x| 3 % x }
514
- enumerable.shuffle!(fake_random)
515
- shuffle2 = enumerable.to_a
516
- original.should_not eq(shuffle1)
517
- original.should_not eq(shuffle2)
518
- shuffle1.should_not eq(shuffle2)
519
- end
520
-
521
- it "contains all of the original elements" do
522
- enumerable.shuffle!.to_a.sort.should eq(collection)
523
- end
524
-
525
- it "does noy alter the original collection" do
526
- original = collection.dup
527
- enumerable.max_array_size = enumerable.size
528
- enumerable.shuffle!
529
- enumerable.to_a.should_not eq(original)
530
- original.should eq(collection)
531
- end
532
-
533
- end
534
-
535
- context "#size" do
536
-
537
- it "returns the current size of the collection" do
538
- enumerable.size.should eql(collection.size)
539
- end
540
-
541
- end
542
-
543
- context "#(private)next_prime" do
544
-
545
- it "should return the next prime following any integer" do
546
- primes = Prime.first(100)
547
- x = 0
548
- until primes.empty?
549
- enumerable.next_prime(x).should eq(primes.first)
550
- x += 1
551
- primes.shift if x.prime?
552
- end
553
- end
554
-
555
- end
556
-
557
- context "#(private)_fetch" do
558
-
559
- context "with an index outside the range of (sequence_start..sequence_end)" do
560
- it "should never relay to fetch" do
561
- enumerable.should_not_receive(:fetch)
562
- enumerable._fetch(-1 * enumerable.size - 1)
563
- enumerable._fetch(enumerable.size)
564
- end
565
- end
566
-
567
- context "with an index inside the range of (sequence_start..sequence_end)" do
568
- it "should relay to fetch" do
569
- enumerable.should_receive(:fetch).twice
570
- enumerable._fetch(0)
571
- enumerable._fetch(enumerable.size - 1)
572
- end
573
-
574
- it "should map the relative index to an absolute index before calling fetch" do
575
- enumerable.shift(3)
576
- enumerable.stub(:shuffle_index) { |index| index + 2 }
577
- enumerable.should_receive(:fetch).with(5)
578
- enumerable._fetch(0)
579
- end
580
-
581
- end
582
-
583
- end
584
-
585
- context "#(private)element_or_array" do
586
-
587
- let(:block) { Proc.new { 1 } }
588
-
589
- context "on a non empty collection" do
590
- context "with no parameter" do
591
- it "returns a single element" do
592
- enumerable.element_or_array { block.call }.should eql(1)
593
- end
594
- end
595
-
596
- context "with a nil parameter" do
597
- it "returns a single element" do
598
- enumerable.element_or_array(nil, &block).should eql(1)
599
- end
600
- end
601
-
602
- context "with a non nil parameter" do
603
- it "returns an array of N elements" do
604
- enumerable.element_or_array(3, &block).should eql([1, 1, 1])
605
- end
606
-
607
- it "will not return more items than remain in the collection" do
608
- size = enumerable.size
609
- enumerable.element_or_array(size + 1, &block).should have(size).items
610
- end
611
- end
612
- end
613
-
614
- context "on an empty collection" do
615
- context "with no parameter" do
616
- it "returns nil" do
617
- emptied_enumerable.element_or_array(&:block).should be_nil
618
- end
619
- end
620
-
621
- context "with a parameter" do
622
- it "returns an empty array" do
623
- emptied_enumerable.element_or_array(3, &block).should eql([])
624
- end
625
- end
626
- end
627
-
628
- it "raises an exception if the parameter is negative" do
629
- expect { enumerable.element_or_array(-1, &block) }.to raise_error(ArgumentError, 'negative array size')
630
- end
631
-
632
- end
633
-
634
- context "#(private)full_cycle_increment" do
635
-
636
- it "must never return a value equal to the domain size" do
637
- (0...100).to_a.all? { |x| enumerable.full_cycle_increment(x) != x }.should be_true
638
- end
639
-
640
- end
641
-
642
- end
data/spec/spec_helper.rb DELETED
@@ -1 +0,0 @@
1
- require 'huge_enumerable'