hash_sample 0.8.5 → 0.8.6

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
  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