hash_sample 0.8.5 → 0.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 96d9552ffc743c9e19465465918840036fc94d6b04097b487d0c18b2ab3a094e
4
- data.tar.gz: ec329877c7b1978caf6dd17a36fd41b0094b64863753a1f890d1b5a5bcc7f529
3
+ metadata.gz: 687ec220029dffa020de6baf5fff22728a6e275f0f9fb4d7a404aae3a4242b6c
4
+ data.tar.gz: 2a11a5e333024cdfa5f956c83394c105d00f77c8d43b17cdfc36aa411d1cc241
5
5
  SHA512:
6
- metadata.gz: 2d026964365bd5fcafb9b349dad30553644cbd3d048cb6a38abeb9c833d3726366f1cce045ce45cfeeb202e3e7aa24a3c5d78940c541ab62bccccfe33302c322
7
- data.tar.gz: 80c85b10012618901bf538e82341349c81608838b26beb2ac9d6237f29a53b5b7c3eda26084e1fefa91bc86b3e14964072f86e6de57d0390e768c2e08c823970
6
+ metadata.gz: c9f37df2db1c8430edc64bdd6a7ad5e26fa06248a66af51106f8e426e98a8c165cb71c7d71c832f96b94a8c0ddc829cf905dac1336f5e2720366427d8dc2fc3d
7
+ data.tar.gz: 3ffaa49c402291f6a68fcfe3d590ece00427ac3c4d0e0920a1e8651bb3fecbb2fcfe177129894d8fa047651e1bf4e11b15252099b68536ab49c18f076e149700
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in the .gemspec file
4
+ gemspec
data/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2020 Sergey Evstegneiev
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Sergey Evstegneiev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md CHANGED
@@ -1,86 +1,88 @@
1
- # hash_sample
2
-
3
- Implements regular sampling and weighted random sampling with and without replacement for Hashes
4
-
5
- ## Installation
6
-
7
- gem install hash_sample
8
-
9
- ## Usage
10
-
11
- ```ruby
12
- require 'hash_sample'
13
- loaded_die = {'1' => 0.1, '2' => 0.1, '3' => 0.1, '4' => 0.1, '5' => 0.1, '6' => 0.5}
14
- p loaded_die.wchoice # "6"
15
- p loaded_die.wchoice(1) # ["6"]
16
- p loaded_die.wchoice(10) # ["4", "6", "3", "3", "2", "2", "1", "6", "4", "6"]
17
- p loaded_die.wsample # 6
18
- p loaded_die.wsample(6) # ["6", "3", "2", "4", "1", "5"]
19
- p loaded_die.wsample(10) # ["2", "6", "1", "3", "4", "5"]
20
- p loaded_die.sample # { '1' => 0.1 }
21
- p loaded_die.sample(6) # {'1' => 0.1, '2' => 0.1, '3' => 0.1, '4' => 0.1, '5' => 0.1, '6' => 0.5}
22
- ```
23
-
24
- ## Hash instance methods
25
- ### hash.sample(n = 1) ⇒ Hash
26
- Choose a random key=>value pair or n random pairs from the hash.
27
-
28
- The key=>value pairs are chosen by using random and unique indices in order to ensure that each pair doesn't includes more than once
29
-
30
- If the hash is empty it returns an empty hash.
31
-
32
- If the hash contains less than n unique keys, the copy of whole hash will be returned, none of keys will be lost due to bad luck.
33
-
34
- Returns new Hash containing sample key=>value pairs
35
-
36
- ### hash.wchoice Object
37
- ### hash.wchoice(n) ⇒ Array of n samples.
38
- Weighted random sampling *with* replacement.
39
-
40
- Choose a random key or n random keys from the hash, according to weights defined in hash values.
41
-
42
- The samples are drawn by using random and replaced by its copy, so they **can be repeated in result**.
43
-
44
- If the hash is empty the first form returns nil and the second form returns an empty array.
45
-
46
- All weights should be Numeric.
47
-
48
- Zero or negative weighs will be ignored.
49
-
50
- {'_' => 9, 'a' => 1}.wchoice(10) # ["_", "a", "_", "_", "_", "_", "_", "_", "_", "_"]
51
-
52
- ### hash.wsample Object
53
- ### hash.wsample(n) ⇒ Array of n samples.
54
- Weighted random sampling *without* replacement.
55
-
56
- Choose 1 or n *distinct* random keys from the hash, according to weights defined in hash values.
57
- Drawn items are not replaced.
58
-
59
- If the hash is empty the first form returns nil and the second form returns an empty array.
60
-
61
- All weights should be Numeric.
62
-
63
- Zero or negative weighs will be ignored.
64
-
65
- {'_' => 9, 'a' => 1}.wchoice(10) # ["_", "a"]
66
-
67
- ### hash.wchoices(n = 1) Object
68
- alias for wchoice
69
-
70
- ### hash.wsamples(n = 1) ⇒ Object
71
- alias for wsample
72
-
73
- ## Contributing
74
-
75
- 1. Fork it ( https://github.com/serg123e/hash_sample/fork )
76
- 2. Create your feature branch (`git checkout -b my-new-feature`)
77
- 3. Commit your changes (`git commit -am 'Add some feature'`)
78
- 4. Push to the branch (`git push origin my-new-feature`)
79
- 5. Create a new Pull Request
80
-
81
- ## References
82
-
83
- 1. [Efraimidis and Spirakis implementation of random sampling with replacement](https://gist.github.com/O-I/3e0654509dd8057b539a)
84
- 2. [Weighted Random Sampling (2005; Efraimidis, Spirakis)](https://utopia.duth.gr/~pefraimi/research/data/2007EncOfAlg.pdf)
85
- 3. [Abandoned Ruby feature request](https://bugs.ruby-lang.org/issues/4247#change-25166)
1
+ # hash_sample
2
+
3
+ [![Build Status](https://travis-ci.com/serg123e/hash_sample.svg?branch=master)](https://travis-ci.com/serg123e/hash_sample)
4
+
5
+ Implements methods for Hash class for getting weighted random samples with and without replacement, as well as regular random samples
6
+
7
+ ## Installation
8
+
9
+ gem install hash_sample
10
+
11
+ ## Usage
12
+
13
+ ```ruby
14
+ require 'hash_sample'
15
+ loaded_die = {'1' => 0.1, '2' => 0.1, '3' => 0.1, '4' => 0.1, '5' => 0.1, '6' => 0.5}
16
+ p loaded_die.wchoice # "6"
17
+ p loaded_die.wchoice(1) # ["6"]
18
+ p loaded_die.wchoice(10) # ["4", "6", "3", "3", "2", "2", "1", "6", "4", "6"]
19
+ p loaded_die.wsample # 6
20
+ p loaded_die.wsample(6) # ["6", "3", "2", "4", "1", "5"]
21
+ p loaded_die.wsample(10) # ["2", "6", "1", "3", "4", "5"]
22
+ p loaded_die.sample # { '1' => 0.1 }
23
+ p loaded_die.sample(6) # {'1' => 0.1, '2' => 0.1, '3' => 0.1, '4' => 0.1, '5' => 0.1, '6' => 0.5}
24
+ ```
25
+
26
+ ## Hash instance methods
27
+ ### hash.sample(n = 1) ⇒ Hash
28
+ Choose a random key=>value pair or n random pairs from the hash.
29
+
30
+ The key=>value pairs are chosen by using random and unique indices in order to ensure that each pair doesn't includes more than once
31
+
32
+ If the hash is empty it returns an empty hash.
33
+
34
+ If the hash contains less than n unique keys, the copy of whole hash will be returned, none of keys will be lost due to bad luck.
35
+
36
+ Returns new Hash containing sample key=>value pairs
37
+
38
+ ### hash.wchoice Object
39
+ ### hash.wchoice(n) ⇒ Array of n samples.
40
+ Weighted random sampling *with* replacement.
41
+
42
+ Choose a random key or n random keys from the hash, according to weights defined in hash values.
43
+
44
+ The samples are drawn by using random and replaced by its copy, so they **can be repeated in result**.
45
+
46
+ If the hash is empty the first form returns nil and the second form returns an empty array.
47
+
48
+ All weights should be Numeric.
49
+
50
+ Zero or negative weighs will be ignored.
51
+
52
+ {'_' => 9, 'a' => 1}.wchoice(10) # ["_", "a", "_", "_", "_", "_", "_", "_", "_", "_"]
53
+
54
+ ### hash.wsample Object
55
+ ### hash.wsample(n) ⇒ Array of n samples.
56
+ Weighted random sampling *without* replacement.
57
+
58
+ Choose 1 or n *distinct* random keys from the hash, according to weights defined in hash values.
59
+ Drawn items are not replaced.
60
+
61
+ If the hash is empty the first form returns nil and the second form returns an empty array.
62
+
63
+ All weights should be Numeric.
64
+
65
+ Zero or negative weighs will be ignored.
66
+
67
+ {'_' => 9, 'a' => 1}.wchoice(10) # ["_", "a"]
68
+
69
+ ### hash.wchoices(n = 1) ⇒ Object
70
+ alias for wchoice
71
+
72
+ ### hash.wsamples(n = 1) ⇒ Object
73
+ alias for wsample
74
+
75
+ ## Contributing
76
+
77
+ 1. Fork it ( https://github.com/serg123e/hash_sample/fork )
78
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
79
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
80
+ 4. Push to the branch (`git push origin my-new-feature`)
81
+ 5. Create a new Pull Request
82
+
83
+ ## References
84
+
85
+ 1. [Efraimidis and Spirakis implementation of random sampling with replacement](https://gist.github.com/O-I/3e0654509dd8057b539a)
86
+ 2. [Weighted Random Sampling (2005; Efraimidis, Spirakis)](https://utopia.duth.gr/~pefraimi/research/data/2007EncOfAlg.pdf)
87
+ 3. [Abandoned Ruby feature request](https://bugs.ruby-lang.org/issues/4247#change-25166)
86
88
  4. [Inspiring example of using max_by for Enumerables with the same algorithm](https://ruby-doc.org/core-2.7.1/Enumerable.html#method-i-max_by)
data/Rakefile CHANGED
@@ -1,156 +1,161 @@
1
- require 'yard'
2
- require 'rake'
3
- require 'date'
4
-
5
- #############################################################################
6
- #
7
- # Helper functions
8
- #
9
- #############################################################################
10
-
11
- def name
12
- "hash_sample"
13
- end
14
-
15
- def version
16
- line = File.read("lib/#{name}/version.rb")[/^\s*VERSION\s*=\s*.*/]
17
- line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
18
- end
19
-
20
- # assumes x.y.z all digit version
21
- def next_version
22
- # x.y.z
23
- v = version.split '.'
24
- # bump z
25
- v[-1] = v[-1].to_i + 1
26
- v.join '.'
27
- end
28
-
29
- def bump_version
30
- old_file = File.read("lib/#{name}/version.rb")
31
- old_version_line = old_file[/^\s*VERSION\s*=\s*.*/]
32
- new_version = next_version
33
- # replace first match of old version with new version
34
- old_file.sub!(old_version_line, " VERSION = '#{new_version}'")
35
-
36
- File.write("lib/#{name}/version.rb", old_file)
37
-
38
- new_version
39
- end
40
-
41
- def replace_header(head, header_name)
42
- head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
43
- end
44
-
45
- def gemspec_file
46
- "#{name}.gemspec"
47
- end
48
-
49
- def gem_files
50
- ["#{name}-#{version}.gem"]
51
- end
52
-
53
- def gemspecs
54
- ["#{name}.gemspec"]
55
- end
56
-
57
- def date
58
- Date.today.to_s
59
- end
60
- #############################################################################
61
- #
62
- # Custom tasks (add your own tasks here)
63
- #
64
- #############################################################################
65
-
66
- YARD::Rake::YardocTask.new do |t|
67
- end
68
-
69
- desc "Generate RCov test coverage and open in your browser"
70
- task :coverage do
71
- require 'rcov'
72
- sh "rm -fr coverage"
73
- sh "rcov test/test_*.rb"
74
- sh "open coverage/index.html"
75
- end
76
-
77
- desc "Open an irb session preloaded with this library"
78
- task :console do
79
- sh "irb -r rubygems -r ./lib/#{name}.rb"
80
- end
81
-
82
- desc "Update version number and gemspec"
83
- task :bump do
84
- puts "Updated version to #{bump_version}"
85
- # Execute does not invoke dependencies.
86
- # Manually invoke gemspec then validate.
87
- Rake::Task[:gemspec].execute
88
- Rake::Task[:validate].execute
89
- end
90
-
91
- desc 'Build gem'
92
- task :build => :gemspec do
93
- sh "mkdir pkg"
94
- gemspecs.each do |gemspec|
95
- sh "gem build #{gemspec}"
96
- end
97
- gem_files.each do |gem_file|
98
- sh "mv #{gem_file} pkg"
99
- end
100
- end
101
-
102
-
103
- desc "Build and install"
104
- task :install => :build do
105
- sh "gem install --local --no-document pkg/#{name}-#{version}.gem"
106
- end
107
-
108
- desc 'Update gemspec'
109
- task :gemspec => :validate do
110
- # read spec file and split out manifest section
111
- spec = File.read(gemspec_file)
112
- head, _manifest, tail = spec.split(/\s*# = MANIFEST =\n/)
113
-
114
- # replace name version and date
115
- replace_header(head, :name)
116
- replace_header(head, :version)
117
- replace_header(head, :date)
118
- #comment this out if your rubyforge_project has a different name
119
- # replace_header(head, :rubyforge_project)
120
-
121
- # determine file list from git ls-files
122
- files = `git ls-files`.
123
- split("\n").
124
- sort.
125
- reject { |file| file =~ /^\./ }.
126
- reject { |file| file =~ /^(rdoc|pkg|test|Home\.md|\.gitattributes|Guardfile)/ }.
127
- map { |file| " #{file}" }.
128
- join("\n")
129
-
130
- # piece file back together and write
131
- manifest = " s.files = %w(\n#{files}\n )"
132
- spec = [head, manifest, tail].join("\n # = MANIFEST =\n")
133
- File.open(gemspec_file, 'w') { |io| io.write(spec) }
134
- puts "Updated #{gemspec_file}"
135
- end
136
-
137
- desc 'Validate lib files and version file'
138
- task :validate do
139
- libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
140
- unless libfiles.empty?
141
- puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
142
- exit!
143
- end
144
- unless Dir['VERSION*'].empty?
145
- puts "A `VERSION` file at root level violates Gem best practices."
146
- exit!
147
- end
148
- end
149
-
150
- begin
151
- require 'rspec/core/rake_task'
152
- desc "run rspec tests"
153
- RSpec::Core::RakeTask.new(:spec)
154
- task :default => :spec
155
- rescue LoadError
1
+ require 'yard'
2
+ require 'rake'
3
+ require 'date'
4
+
5
+ #############################################################################
6
+ #
7
+ # Helper functions
8
+ #
9
+ #############################################################################
10
+
11
+ def name
12
+ "hash_sample"
13
+ end
14
+
15
+ def version
16
+ line = File.read("lib/#{name}/version.rb")[/^\s*VERSION\s*=\s*.*/]
17
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
18
+ end
19
+
20
+ # assumes x.y.z all digit version
21
+ def next_version
22
+ # x.y.z
23
+ v = version.split '.'
24
+ # bump z
25
+ v[-1] = v[-1].to_i + 1
26
+ v.join '.'
27
+ end
28
+
29
+ def bump_version
30
+ old_file = File.read("lib/#{name}/version.rb")
31
+ old_version_line = old_file[/^\s*VERSION\s*=\s*.*/]
32
+ new_version = next_version
33
+ # replace first match of old version with new version
34
+ old_file.sub!(old_version_line, " VERSION = '#{new_version}'")
35
+
36
+ File.write("lib/#{name}/version.rb", old_file)
37
+ new_version
38
+ end
39
+
40
+ def replace_header(head, header_name)
41
+ head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
42
+ end
43
+
44
+ def gemspec_file
45
+ "#{name}.gemspec"
46
+ end
47
+
48
+ def gem_files
49
+ ["#{name}-#{version}.gem"]
50
+ end
51
+
52
+ def gemspecs
53
+ ["#{name}.gemspec"]
54
+ end
55
+
56
+ def date
57
+ Date.today.to_s
58
+ end
59
+ #############################################################################
60
+ #
61
+ # Custom tasks (add your own tasks here)
62
+ #
63
+ #############################################################################
64
+
65
+ YARD::Rake::YardocTask.new do |t|
66
+ end
67
+
68
+ desc "Generate RCov test coverage and open in your browser"
69
+ task :coverage do
70
+ require 'rcov'
71
+ sh "rm -fr coverage"
72
+ sh "rcov test/test_*.rb"
73
+ sh "open coverage/index.html"
74
+ end
75
+
76
+ desc "Open an irb session preloaded with this library"
77
+ task :console do
78
+ sh "irb -r rubygems -r ./lib/#{name}.rb"
79
+ end
80
+
81
+ desc "Update version number and gemspec"
82
+ task :bump do
83
+ puts "Updated version to #{bump_version}"
84
+ # Execute does not invoke dependencies.
85
+ # Manually invoke gemspec then validate.
86
+ Rake::Task[:gemspec].execute
87
+ Rake::Task[:validate].execute
88
+ end
89
+
90
+ desc 'Build gem'
91
+ task :build => :gemspec do
92
+ sh "mkdir pkg"
93
+ gemspecs.each do |gemspec|
94
+ sh "gem build #{gemspec}"
95
+ end
96
+ gem_files.each do |gem_file|
97
+ sh "mv #{gem_file} pkg"
98
+ end
99
+ end
100
+
101
+
102
+ desc "Build and install"
103
+ task :install => :build do
104
+ sh "gem install --local --no-document pkg/#{name}-#{version}.gem"
105
+ end
106
+
107
+ desc 'Update gemspec'
108
+ task :gemspec => :validate do
109
+ # read spec file and split out manifest section
110
+ spec = File.read(gemspec_file)
111
+ head, _manifest, tail = spec.split(/\s*# = MANIFEST =\n/)
112
+
113
+ # replace name version and date
114
+ replace_header(head, :name)
115
+ replace_header(head, :version)
116
+ replace_header(head, :date)
117
+ #comment this out if your rubyforge_project has a different name
118
+ # replace_header(head, :rubyforge_project)
119
+
120
+ # determine file list from git ls-files
121
+ files = `git ls-files`.
122
+ split("\n").
123
+ sort.
124
+ reject { |file| file =~ /^\./ }.
125
+ reject { |file| file =~ /^(rdoc|pkg|test|Home\.md|\.gitattributes|Guardfile)/ }.
126
+ map { |file| " #{file}" }.
127
+ join("\n")
128
+
129
+ # piece file back together and write
130
+ manifest = " s.files = %w(\n#{files}\n )"
131
+ spec = [head, manifest, tail].join("\n # = MANIFEST =\n")
132
+ File.open(gemspec_file, 'w') { |io| io.write(spec) }
133
+ puts "Updated #{gemspec_file}"
134
+ end
135
+
136
+ desc 'Validate lib files and version file'
137
+ task :validate do
138
+ libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
139
+ unless libfiles.empty?
140
+ puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
141
+ exit!
142
+ end
143
+ unless Dir['VERSION*'].empty?
144
+ puts "A `VERSION` file at root level violates Gem best practices."
145
+ exit!
146
+ end
147
+ end
148
+
149
+ desc 'Tag commit and push it'
150
+ task :tag do
151
+ sh "git tag v#{version}"
152
+ sh "git push --tags"
153
+ end
154
+
155
+ begin
156
+ require 'rspec/core/rake_task'
157
+ desc "run rspec tests"
158
+ RSpec::Core::RakeTask.new(:spec)
159
+ task :default => :spec
160
+ rescue LoadError
156
161
  end
data/hash_sample.gemspec CHANGED
@@ -1,36 +1,42 @@
1
- Gem::Specification.new do |s|
2
- s.name = 'hash_sample'
3
- s.platform = Gem::Platform::RUBY
4
- s.authors = ["Sergey Evstegneiev"]
5
- s.email = ["serg123e@gmail.com"]
6
- s.homepage = 'https://github.com/serg123e/hash_sample'
7
- s.summary = %q{Implements multiple sampling methods for Hash class}
8
- s.description = %q{Regular and weighted random sampling with and without replacement are implemented}
9
- # s.metadata = { 'source_code_uri' => 'https://github.com/serg123e/hash-sample' }
10
- s.add_development_dependency "rspec", "~> 3.5"
11
- s.add_development_dependency "rake", "~> 13"
12
-
13
- s.require_paths = ["lib"]
14
-
15
- s.required_ruby_version = '>= 2.4'
16
-
17
- s.date = '2020-05-01'
18
- s.version = '0.8.5'
19
- s.license = 'MIT'
20
-
21
- s.rdoc_options = ['--charset=UTF-8']
22
- s.extra_rdoc_files = %w(README.md LICENSE)
23
- # = MANIFEST =
24
- s.files = %w(
25
- LICENSE
26
- README.md
27
- Rakefile
28
- hash_sample.gemspec
29
- lib/hash_sample.rb
30
- lib/hash_sample/version.rb
31
- spec/hash_sample_spec.rb
32
- spec/spec_helper.rb
33
- )
34
- # = MANIFEST =
35
- s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
1
+ Gem::Specification.new do |s|
2
+ s.name = 'hash_sample'
3
+ s.platform = Gem::Platform::RUBY
4
+ s.authors = ["Sergey Evstegneiev"]
5
+ s.email = ["serg123e@gmail.com"]
6
+ s.homepage = 'https://github.com/serg123e/hash_sample'
7
+ s.summary = %q{Implements multiple sampling methods for Hash class}
8
+ s.description = %q{Implements methods for Hash class for getting weighted random samples with and without replacement, as well as regular random samples}
9
+
10
+ s.add_development_dependency "rspec", "~> 3.5"
11
+ s.add_development_dependency "simplecov", "~> 0.12"
12
+ s.add_development_dependency "rspec-simplecov", "~> 0.2"
13
+
14
+ s.add_development_dependency "rake", "~> 13"
15
+ s.add_development_dependency "yard", "~> 0.9"
16
+
17
+
18
+ s.require_paths = ["lib"]
19
+
20
+ s.required_ruby_version = '>= 2.4'
21
+
22
+ s.date = '2020-05-01'
23
+ s.version = '0.8.6'
24
+ s.license = 'MIT'
25
+
26
+ s.rdoc_options = ['--charset=UTF-8']
27
+ s.extra_rdoc_files = %w(README.md LICENSE)
28
+ # = MANIFEST =
29
+ s.files = %w(
30
+ Gemfile
31
+ LICENSE
32
+ README.md
33
+ Rakefile
34
+ hash_sample.gemspec
35
+ lib/hash_sample.rb
36
+ lib/hash_sample/version.rb
37
+ spec/hash_sample_spec.rb
38
+ spec/spec_helper.rb
39
+ )
40
+ # = MANIFEST =
41
+ s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
36
42
  end
@@ -1,4 +1,4 @@
1
- module HashSample
2
- # gem version
3
- VERSION = '0.8.5'
1
+ module HashSample
2
+ # gem version
3
+ VERSION = '0.8.6'
4
4
  end
data/lib/hash_sample.rb CHANGED
@@ -1,94 +1,94 @@
1
- # monkey-patched Hash module
2
- class Hash
3
- ##
4
- # Choose a random key=>value pair or *n* random pairs from the hash.
5
- #
6
- # @return [Hash] new Hash containing sample key=>value pairs
7
- #
8
- # The elements are chosen by using random and unique indices in order to ensure that each element doesn't includes more than once.
9
- # If the hash is empty it returns an empty hash.
10
- # If the hash contains less than *n* unique keys, the copy of whole hash will be returned, none of keys will be lost.
11
- def sample(n = 1)
12
- to_a.sample(n).to_h
13
- end
14
-
15
- ###
16
- # alias for wchoice
17
- def wchoices(*args)
18
- wchoice(*args)
19
- end
20
-
21
- ##
22
- # Choose 1 or n random keys from the hash, according to weights defined in hash values
23
- # (weighted random sampling *with* *replacement*)
24
- #
25
- # @overload wchoice
26
- # @return [Object] one sample object
27
- # @overload wchoice(n)
28
- # @param n [Integer] number of samples to be returned
29
- # @return [Array] Array of n samples
30
- #
31
- # The keys are chosen by using random according to its weights and *can* *be* *repeated* *in* *result*.
32
- # If the hash is empty the first form returns nil and the second form returns an empty array.
33
- # All weights should be Numeric.
34
- # Zero or negative weighs will be ignored.
35
- #
36
- # ===== Example
37
- #
38
- # p {'_' => 9, 'a' => 1}.wchoice(10) # ["_", "a", "_", "_", "_", "_", "_", "_", "_", "_"]
39
- #
40
- def wchoice(*args)
41
- _check_weighted_params
42
- n = args.first || 1
43
- res = []
44
- n.times do
45
- tmp = max_by { |_, weight| weight.positive? ? rand**(1.0 / weight) : 0 }
46
- res << tmp.first unless tmp.nil?
47
- end
48
- return args.empty? ? res.first : res
49
- end
50
-
51
- # internal method to validate parameters
52
- def _check_weighted_params(*_args)
53
- sum_weights = 0
54
- each_value do |v|
55
- raise ArgumentError, "All weights should be numeric unlike #{v}" unless v.is_a? Numeric
56
-
57
- sum_weights += v if v.positive?
58
- end
59
-
60
- raise ArgumentError, "At least one weight should be > 0" unless sum_weights.positive? || empty?
61
- end
62
-
63
- ##
64
- # Choose 1 or n *distinct* random keys from the hash, according to weights defined in hash values
65
- # (weighted random sampling *without* *replacement*)
66
- #
67
- # @overload wsample
68
- # @return [Object] one sample object
69
- # @overload wsample(n)
70
- # @param n [Integer] number of samples to be returned
71
- # @return [Array] Array of n or sometimes less than n samples
72
- #
73
- # When there are no sufficient distinct samples to return, the result will contain less than n samples
74
- # If the hash is empty the first form returns nil and the second form returns an empty array.
75
- # All weights should be Numeric.
76
- # Zero or negative weighs will be ignored.
77
- #
78
- # ===== Example
79
- #
80
- # p {'_' => 9, 'a' => 1}.wsample(10) # ["_", "a"]
81
- #
82
- def wsample(*args)
83
- _check_weighted_params
84
- n = args.first || 1
85
- res = max_by(n) { |_, weight| weight.positive? ? rand**(1.0 / weight) : 0 }.map(&:first)
86
- return args.empty? ? res.first : res
87
- end
88
-
89
- ###
90
- # alias for wsample
91
- def wsamples(*args)
92
- wsample(*args)
93
- end
94
- end
1
+ # monkey-patched Hash module
2
+ class Hash
3
+ ##
4
+ # Choose a random key=>value pair or *n* random pairs from the hash.
5
+ #
6
+ # @return [Hash] new Hash containing sample key=>value pairs
7
+ #
8
+ # The elements are chosen by using random and unique indices in order to ensure that each element doesn't includes more than once.
9
+ # If the hash is empty it returns an empty hash.
10
+ # If the hash contains less than *n* unique keys, the copy of whole hash will be returned, none of keys will be lost.
11
+ def sample(n = 1)
12
+ to_a.sample(n).to_h
13
+ end
14
+
15
+ ###
16
+ # alias for wchoice
17
+ def wchoices(*args)
18
+ wchoice(*args)
19
+ end
20
+
21
+ ##
22
+ # Choose 1 or n random keys from the hash, according to weights defined in hash values
23
+ # (weighted random sampling *with* *replacement*)
24
+ #
25
+ # @overload wchoice
26
+ # @return [Object] one sample object
27
+ # @overload wchoice(n)
28
+ # @param n [Integer] number of samples to be returned
29
+ # @return [Array] Array of n samples
30
+ #
31
+ # The keys are chosen by using random according to its weights and *can* *be* *repeated* *in* *result*.
32
+ # If the hash is empty the first form returns nil and the second form returns an empty array.
33
+ # All weights should be Numeric.
34
+ # Zero or negative weighs will be ignored.
35
+ #
36
+ # ===== Example
37
+ #
38
+ # p {'_' => 9, 'a' => 1}.wchoice(10) # ["_", "a", "_", "_", "_", "_", "_", "_", "_", "_"]
39
+ #
40
+ def wchoice(*args)
41
+ _check_weighted_params
42
+ n = args.first || 1
43
+ res = []
44
+ n.times do
45
+ tmp = max_by { |_, weight| weight.positive? ? rand**(1.0 / weight) : 0 }
46
+ res << tmp.first unless tmp.nil?
47
+ end
48
+ return args.empty? ? res.first : res
49
+ end
50
+
51
+ # internal method to validate parameters
52
+ def _check_weighted_params(*_args)
53
+ sum_weights = 0
54
+ each_value do |v|
55
+ raise ArgumentError, "All weights should be numeric unlike #{v}" unless v.is_a? Numeric
56
+
57
+ sum_weights += v if v.positive?
58
+ end
59
+
60
+ raise ArgumentError, "At least one weight should be > 0" unless sum_weights.positive? || empty?
61
+ end
62
+
63
+ ##
64
+ # Choose 1 or n *distinct* random keys from the hash, according to weights defined in hash values
65
+ # (weighted random sampling *without* *replacement*)
66
+ #
67
+ # @overload wsample
68
+ # @return [Object] one sample object
69
+ # @overload wsample(n)
70
+ # @param n [Integer] number of samples to be returned
71
+ # @return [Array] Array of n or sometimes less than n samples
72
+ #
73
+ # When there are no sufficient distinct samples to return, the result will contain less than n samples
74
+ # If the hash is empty the first form returns nil and the second form returns an empty array.
75
+ # All weights should be Numeric.
76
+ # Zero or negative weighs will be ignored.
77
+ #
78
+ # ===== Example
79
+ #
80
+ # p {'_' => 9, 'a' => 1}.wsample(10) # ["_", "a"]
81
+ #
82
+ def wsample(*args)
83
+ _check_weighted_params
84
+ n = args.first || 1
85
+ res = max_by(n) { |_, weight| weight.positive? ? rand**(1.0 / weight) : 0 }.map(&:first)
86
+ return args.empty? ? res.first : res
87
+ end
88
+
89
+ ###
90
+ # alias for wsample
91
+ def wsamples(*args)
92
+ wsample(*args)
93
+ end
94
+ end
@@ -1,168 +1,168 @@
1
- # require 'lib/core_ext.rb'
2
-
3
- #
4
- # Specs
5
- #
6
- describe 'Hash#sample' do
7
- describe 'when specified parameter n>1' do
8
- it 'returns new Hash with specified number of unique key=>value samples' do
9
- h = { 'a' => 'b', 'b' => 'b', 'c' => 'b' }
10
- expect(h.sample(3)).to eq h
11
- end
12
- end
13
- describe 'when specified parameter n> number of unique keys' do
14
- it 'returns new Hash only with unique key=>value samples' do
15
- h = { 'a' => 'b', 'b' => 'b', 'c' => 'b' }
16
- expect(h.sample(10)).to eq h
17
- end
18
- end
19
-
20
- describe 'when specified parameter n> number of unique keys' do
21
- it 'keys can not be lost because of bad luck' do
22
- h = { 'a' => 'b', 'b' => 'b', 'c' => 'b' }
23
- min = h.keys.length
24
- 100.times do
25
- min = [h.sample(4).keys.length, min].min
26
- end
27
- expect(min).to be 3
28
- end
29
- end
30
-
31
- describe 'when specified parameter n==1' do
32
- it 'returns new Hash with 1 random key=>value sample' do
33
- h = { 'a' => 'b', 'b' => 'b', 'c' => 'b' }
34
- expect(h.sample(1).keys.length).to eq 1
35
- end
36
- end
37
- end
38
-
39
- %w[wchoice wsample].each do |weighted_method|
40
- describe 'plural form of method' do
41
- weighted_methods = weighted_method + "s"
42
- it 'can be used' do
43
- expect({}).to respond_to(weighted_methods)
44
- end
45
- it 'works as expected without args' do
46
- expect({ 'a' => 1 }.send(weighted_methods)).to eq 'a'
47
- end
48
- it 'works as expected with args' do
49
- expect({ 'a' => 1 }.send(weighted_methods, 1)).to eq ['a']
50
- end
51
- end
52
-
53
- describe "Hash\##{weighted_method}" do
54
- it 'returns weighted sample key from all keys with respect of its weights' do
55
- s = { 1 => 90, 2 => 10 }
56
- freq = Hash.new(0)
57
- 1000.times { freq[s.send(weighted_method)] += 1 }
58
- expect(freq[1]).to be_between(800, 999)
59
- expect(freq[2]).to be_between(1, 200)
60
- end
61
-
62
- describe 'when weights are equal' do
63
- it 'it should returns equal parts of samples' do
64
- res = 1.upto(100_000).to_a.map { { +1 => 50, -1 => 50 }.send(weighted_method) }
65
- expect(res.sum).to be_between(-1000, 1000) # +-1% bias
66
- end
67
- end
68
-
69
- describe 'when Hash is empty' do
70
- it 'returns nil' do
71
- expect({}.send(weighted_method)).to be_nil
72
- end
73
- end
74
-
75
- describe 'when weights are Float' do
76
- it 'returns a value as expected' do
77
- expect([1, 2].include?({ 1 => 0.1, 2 => 0.9 }.send(weighted_method))).to be true
78
- end
79
- end
80
-
81
- describe 'when some weights are negative' do
82
- it 'does not sample that key' do
83
- 100.times { expect({ 'a' => -1, 'b' => 2 }.send(weighted_method)).to eq 'b' }
84
- end
85
- end
86
-
87
- describe 'when weight contains zero' do
88
- it 'returns non-zero weighted element' do
89
- 10.times do
90
- expect({ 1 => 0, 2 => 1, 3 => 0 }.send(weighted_method)).to eq 2
91
- end
92
- end
93
- end
94
-
95
- describe 'when weight is non-numeric' do
96
- it 'raises ArgumentError' do
97
- expect { { 1 => 'asd', 2 => 2 }.send(weighted_method) }.to raise_error(ArgumentError)
98
- end
99
- end
100
-
101
- describe 'when all weights are zero' do
102
- it 'raises ArgumentError' do
103
- expect { { 1 => 0, 2 => 0 }.send(weighted_method) }.to raise_error(ArgumentError)
104
- end
105
- # @todo do not raise error when all weights are zero
106
- # xit 'returns empty array' do
107
- # h = { 'a'=>0, 'b'=>0, 'c'=>0 }
108
- # expect( h.wchoice(10) ).to eq []
109
- # end
110
- end
111
-
112
- describe 'when hash is empty' do
113
- it 'returns empty array or nil' do
114
- expect({}.send(weighted_method, 10)).to eq []
115
- expect({}.send(weighted_method)).to eq nil
116
- end
117
- end
118
-
119
- describe 'when specified parameter n>1' do
120
- it 'returns array of sample keys 2' do
121
- 100.times { expect({ 1 => 1, 2 => 0.01, 3 => 0.0000001 }.wchoice(3).length).to be 3 }
122
- end
123
- end
124
- describe 'when specified parameter n==1' do
125
- subject { { '1' => 1, '2' => 1, '3' => 1 }.wchoice(1) }
126
- it 'returns array of one key' do
127
- expect(subject).to be_kind_of(Array)
128
- expect(subject.length).to be 1
129
- end
130
- end
131
-
132
- describe 'should work with complex Objetcts as keys' do
133
- subject { { %w[asd zxf] => 1, %w[asd bsd] => 1, %w[asd dsf] => 1 }.wchoice }
134
- it 'returns array of one key' do
135
- expect(subject).to be_kind_of(Array)
136
- expect(subject.length).to be 2
137
- expect(subject).to include 'asd'
138
- end
139
- end
140
-
141
- describe 'when specified parameter n is greater than number of unique keys' do
142
- it 'returns array with exactly n key samples, repeating some of them' do
143
- h = { 'a' => 1, 'b' => 1, 'c' => 1 }
144
- expect(h.wchoice(10).length).to eq 10
145
- end
146
- end
147
- end
148
- end
149
-
150
- describe 'Hash#wchoice' do
151
- describe 'when specified parameter n>1' do
152
- it 'returns array of n sample keys' do
153
- expect({ 'a' => 1 }.wchoice(2)).to eq %w[a a]
154
- end
155
- end
156
- end
157
-
158
- describe 'Hash#wsample' do
159
- describe 'when specified parameter n>1' do
160
- it 'returns array of unique keys' do
161
- expect({ 'a' => 1 }.wsample(2)).to eq ['a']
162
- end
163
- end
164
-
165
- it 'returned objects are not repeated' do
166
- expect({ '_' => 9, 'a' => 1 }.wsample(10).sort).to eq %w[_ a]
167
- end
168
- end
1
+ # require 'lib/core_ext.rb'
2
+
3
+ #
4
+ # Specs
5
+ #
6
+ describe 'Hash#sample' do
7
+ describe 'when specified parameter n>1' do
8
+ it 'returns new Hash with specified number of unique key=>value samples' do
9
+ h = { 'a' => 'b', 'b' => 'b', 'c' => 'b' }
10
+ expect(h.sample(3)).to eq h
11
+ end
12
+ end
13
+ describe 'when specified parameter n> number of unique keys' do
14
+ it 'returns new Hash only with unique key=>value samples' do
15
+ h = { 'a' => 'b', 'b' => 'b', 'c' => 'b' }
16
+ expect(h.sample(10)).to eq h
17
+ end
18
+ end
19
+
20
+ describe 'when specified parameter n> number of unique keys' do
21
+ it 'keys can not be lost because of bad luck' do
22
+ h = { 'a' => 'b', 'b' => 'b', 'c' => 'b' }
23
+ min = h.keys.length
24
+ 100.times do
25
+ min = [h.sample(4).keys.length, min].min
26
+ end
27
+ expect(min).to be 3
28
+ end
29
+ end
30
+
31
+ describe 'when specified parameter n==1' do
32
+ it 'returns new Hash with 1 random key=>value sample' do
33
+ h = { 'a' => 'b', 'b' => 'b', 'c' => 'b' }
34
+ expect(h.sample(1).keys.length).to eq 1
35
+ end
36
+ end
37
+ end
38
+
39
+ %w[wchoice wsample].each do |weighted_method|
40
+ describe 'plural form of method' do
41
+ weighted_methods = weighted_method + "s"
42
+ it 'can be used' do
43
+ expect({}).to respond_to(weighted_methods)
44
+ end
45
+ it 'works as expected without args' do
46
+ expect({ 'a' => 1 }.send(weighted_methods)).to eq 'a'
47
+ end
48
+ it 'works as expected with args' do
49
+ expect({ 'a' => 1 }.send(weighted_methods, 1)).to eq ['a']
50
+ end
51
+ end
52
+
53
+ describe "Hash\##{weighted_method}" do
54
+ it 'returns weighted sample key from all keys with respect of its weights' do
55
+ s = { 1 => 90, 2 => 10 }
56
+ freq = Hash.new(0)
57
+ 1000.times { freq[s.send(weighted_method)] += 1 }
58
+ expect(freq[1]).to be_between(800, 999)
59
+ expect(freq[2]).to be_between(1, 200)
60
+ end
61
+
62
+ describe 'when weights are equal' do
63
+ it 'it should returns equal parts of samples' do
64
+ res = 1.upto(100_000).to_a.map { { +1 => 50, -1 => 50 }.send(weighted_method) }
65
+ expect(res.sum).to be_between(-1000, 1000) # +-1% bias
66
+ end
67
+ end
68
+
69
+ describe 'when Hash is empty' do
70
+ it 'returns nil' do
71
+ expect({}.send(weighted_method)).to be_nil
72
+ end
73
+ end
74
+
75
+ describe 'when weights are Float' do
76
+ it 'returns a value as expected' do
77
+ expect([1, 2].include?({ 1 => 0.1, 2 => 0.9 }.send(weighted_method))).to be true
78
+ end
79
+ end
80
+
81
+ describe 'when some weights are negative' do
82
+ it 'does not sample that key' do
83
+ 100.times { expect({ 'a' => -1, 'b' => 2 }.send(weighted_method)).to eq 'b' }
84
+ end
85
+ end
86
+
87
+ describe 'when weight contains zero' do
88
+ it 'returns non-zero weighted element' do
89
+ 10.times do
90
+ expect({ 1 => 0, 2 => 1, 3 => 0 }.send(weighted_method)).to eq 2
91
+ end
92
+ end
93
+ end
94
+
95
+ describe 'when weight is non-numeric' do
96
+ it 'raises ArgumentError' do
97
+ expect { { 1 => 'asd', 2 => 2 }.send(weighted_method) }.to raise_error(ArgumentError)
98
+ end
99
+ end
100
+
101
+ describe 'when all weights are zero' do
102
+ it 'raises ArgumentError' do
103
+ expect { { 1 => 0, 2 => 0 }.send(weighted_method) }.to raise_error(ArgumentError)
104
+ end
105
+ # @todo do not raise error when all weights are zero
106
+ # xit 'returns empty array' do
107
+ # h = { 'a'=>0, 'b'=>0, 'c'=>0 }
108
+ # expect( h.wchoice(10) ).to eq []
109
+ # end
110
+ end
111
+
112
+ describe 'when hash is empty' do
113
+ it 'returns empty array or nil' do
114
+ expect({}.send(weighted_method, 10)).to eq []
115
+ expect({}.send(weighted_method)).to eq nil
116
+ end
117
+ end
118
+
119
+ describe 'when specified parameter n>1' do
120
+ it 'returns array of sample keys 2' do
121
+ 100.times { expect({ 1 => 1, 2 => 0.01, 3 => 0.0000001 }.wchoice(3).length).to be 3 }
122
+ end
123
+ end
124
+ describe 'when specified parameter n==1' do
125
+ subject { { '1' => 1, '2' => 1, '3' => 1 }.wchoice(1) }
126
+ it 'returns array of one key' do
127
+ expect(subject).to be_kind_of(Array)
128
+ expect(subject.length).to be 1
129
+ end
130
+ end
131
+
132
+ describe 'should work with complex Objetcts as keys' do
133
+ subject { { %w[asd zxf] => 1, %w[asd bsd] => 1, %w[asd dsf] => 1 }.wchoice }
134
+ it 'returns array of one key' do
135
+ expect(subject).to be_kind_of(Array)
136
+ expect(subject.length).to be 2
137
+ expect(subject).to include 'asd'
138
+ end
139
+ end
140
+
141
+ describe 'when specified parameter n is greater than number of unique keys' do
142
+ it 'returns array with exactly n key samples, repeating some of them' do
143
+ h = { 'a' => 1, 'b' => 1, 'c' => 1 }
144
+ expect(h.wchoice(10).length).to eq 10
145
+ end
146
+ end
147
+ end
148
+ end
149
+
150
+ describe 'Hash#wchoice' do
151
+ describe 'when specified parameter n>1' do
152
+ it 'returns array of n sample keys' do
153
+ expect({ 'a' => 1 }.wchoice(2)).to eq %w[a a]
154
+ end
155
+ end
156
+ end
157
+
158
+ describe 'Hash#wsample' do
159
+ describe 'when specified parameter n>1' do
160
+ it 'returns array of unique keys' do
161
+ expect({ 'a' => 1 }.wsample(2)).to eq ['a']
162
+ end
163
+ end
164
+
165
+ it 'returned objects are not repeated' do
166
+ expect({ '_' => 9, 'a' => 1 }.wsample(10).sort).to eq %w[_ a]
167
+ end
168
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,7 @@
1
- require 'simplecov'
2
- require 'rspec/simplecov'
3
-
4
- SimpleCov.minimum_coverage 100
5
- SimpleCov.start
6
-
7
- require 'hash_sample'
1
+ require 'simplecov'
2
+ require 'rspec/simplecov'
3
+
4
+ SimpleCov.minimum_coverage 100
5
+ SimpleCov.start
6
+
7
+ require 'hash_sample'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hash_sample
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.5
4
+ version: 0.8.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sergey Evstegneiev
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: simplecov
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.12'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.12'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec-simplecov
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.2'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.2'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: rake
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -38,8 +66,22 @@ dependencies:
38
66
  - - "~>"
39
67
  - !ruby/object:Gem::Version
40
68
  version: '13'
41
- description: Regular and weighted random sampling with and without replacement are
42
- implemented
69
+ - !ruby/object:Gem::Dependency
70
+ name: yard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.9'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.9'
83
+ description: Implements methods for Hash class for getting weighted random samples
84
+ with and without replacement, as well as regular random samples
43
85
  email:
44
86
  - serg123e@gmail.com
45
87
  executables: []
@@ -48,6 +90,7 @@ extra_rdoc_files:
48
90
  - README.md
49
91
  - LICENSE
50
92
  files:
93
+ - Gemfile
51
94
  - LICENSE
52
95
  - README.md
53
96
  - Rakefile
@@ -77,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
77
120
  version: '0'
78
121
  requirements: []
79
122
  rubyforge_project:
80
- rubygems_version: 2.7.6.2
123
+ rubygems_version: 2.7.7
81
124
  signing_key:
82
125
  specification_version: 4
83
126
  summary: Implements multiple sampling methods for Hash class