weighted_shuffle 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore CHANGED
@@ -3,3 +3,5 @@ pkg/
3
3
  bin/
4
4
  .bundle/
5
5
  coverage/
6
+ *.gem
7
+ Gemfile.lock
@@ -2,13 +2,6 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
- - ruby-head
6
5
  - jruby-19mode
7
- - jruby-head
8
- - rbx-19mode
9
- - rbx-head
6
+ - rbx-2.1.1
10
7
  script: bundle exec rspec
11
- matrix:
12
- allow_failures:
13
- - rvm: rbx-19mode
14
- - rvm: rbx-head
data/README.md CHANGED
@@ -39,6 +39,10 @@ integrated into ruby Array:
39
39
  array.weighted_shuffle
40
40
  => [:b, :a]
41
41
 
42
+ or with factor
43
+
44
+ array.weighted_shuffle factor: 3
45
+
42
46
  ## Contributing
43
47
 
44
48
  1. Fork it
@@ -1,6 +1,6 @@
1
1
  class Array
2
2
 
3
- def weighted_shuffle
4
- WeightedShuffle::Dealer.new(self).weighted_shuffle
3
+ def weighted_shuffle(options = {})
4
+ WeightedShuffle::Dealer.new(self).weighted_shuffle options
5
5
  end
6
6
  end
@@ -3,13 +3,17 @@ require 'active_support/core_ext/enumerable'
3
3
  module WeightedShuffle
4
4
  class Dealer < Struct.new(:array)
5
5
 
6
- def weighted_shuffle
6
+ def weighted_shuffle(options = {})
7
+ factor = options.delete(:factor)
7
8
  a = Marshal.load Marshal.dump(array)
8
- sum = a.sum { |k,v| v || 0.0 }
9
+ unless factor.nil?
10
+ a.map! { |k, v| [k, v**factor] }
11
+ end
12
+ sum = a.sum { |k, v| v || 0.0 }
9
13
  b = []
10
14
  a.length.times do
11
15
  random = SecureRandom.random_number * sum
12
- a.each_with_index do |(k,v),j|
16
+ a.each_with_index do |(k, v), j|
13
17
  if random <= v
14
18
  b << a.delete_at(j).first
15
19
  sum -= v
@@ -1,4 +1,4 @@
1
1
  module WeightedShuffle
2
2
  # weighted_shuffle version
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.0"
4
4
  end
@@ -3,33 +3,63 @@ require 'spec_helper'
3
3
  module WeightedShuffle
4
4
  describe Dealer do
5
5
  describe '#weighted_shuffle' do
6
- [[ [[:a, 1], [:b, 2]], [:a, :b] ],
7
- [ [[1, 1], [2, 3]], [1, 2] ],
8
- [ [[2.0, 1], [:a, 1.5], ['a', 2.3]], [2.0, :a, 'a'] ]]
9
- .each do |input, output|
10
-
11
- it "returns a permutation of #{output} given #{input}" do
12
- output.permutation.to_a.should include(
13
- Dealer.new(input).weighted_shuffle)
6
+
7
+ context 'without factor' do
8
+ [[ [[:a, 1], [:b, 2]], [:a, :b] ],
9
+ [ [[1, 1], [2, 3]], [1, 2] ],
10
+ [ [[1, 1], [2, 0]], [1, 2] ],
11
+ [ [[1, 1], [2, 0], [3, 0]], [1, 2, 3] ],
12
+ [ [[2.0, 1], [:a, 1.5], ['a', 2.3]], [2.0, :a, 'a'] ]]
13
+ .each do |input, output|
14
+
15
+ it "returns a permutation of #{output} given #{input}" do
16
+ expect(output.permutation.to_a).to include(
17
+ Dealer.new(input).weighted_shuffle)
18
+ end
19
+
20
+ it 'gives correct relative frequency for first position' do
21
+ weights = input.map(&:last)
22
+ # calculate probabiities
23
+ sum = weights.sum
24
+ probabilities = weights.map { |weight| weight.to_f / sum }
25
+
26
+ # establish frequencies
27
+ size = 1000
28
+ samples = size.times.map { Dealer.new(input).weighted_shuffle }
29
+ frequencies = input.map(&:first).map do |e|
30
+ samples.select { |s| s.first == e }.count.to_f / size
31
+ end
32
+
33
+ # calculate sum of absolute values of differences
34
+ diff = probabilities.zip(frequencies).map { |p,f| (p - f).abs }.sum
35
+ expect(diff).to be < 0.1
36
+ end
14
37
  end
38
+ end
15
39
 
16
- it 'gives correct relative frequency for first position' do
17
- weights = input.map(&:last)
18
- # calculate probabiities
19
- sum = weights.sum
20
- probabilities = weights.map { |e| e.to_f / sum }
40
+ context 'with factor' do
21
41
 
22
- # establish frequencies
42
+ it 'big factor has a big impact' do
43
+ input = [[1, 1], [2, 1], [3, 1.01]]
44
+ samples = 10_000.times.map do
45
+ Dealer.new(input).weighted_shuffle factor: 100_000
46
+ end
47
+ expect(samples.map(&:first).count(3)).to eq(samples.size)
48
+ end
49
+
50
+ it 'gives expected relative frequency ' do
51
+ input = [[:a, 1], [:b, 2]]
23
52
  size = 1000
24
- sample = size.times.map { Dealer.new(input).weighted_shuffle }
25
- frequencies = input.map(&:first)
26
- .map do |e|
27
- sample.select { |s| s.first == e }.count.to_f / size
28
- end
53
+ samples = size.times.map do
54
+ Dealer.new(input).weighted_shuffle factor: 2
55
+ end
56
+ frequencies = input.map(&:first).map do |e|
57
+ samples.select { |sample| sample.first == e }.count.to_f / size
58
+ end
29
59
 
30
- # calculate sum of absolute values of differences
31
- diff = probabilities.zip(frequencies).map { |p,f| (p - f).abs }.sum
32
- diff.should < 0.1
60
+ diff = [1.0 / 5, 4.0 / 5].zip(frequencies).map { |p, f| (p - f).abs }
61
+ .sum
62
+ expect(diff).to be < 0.1
33
63
  end
34
64
  end
35
65
  end
@@ -7,7 +7,7 @@ Gem::Specification.new do |gem|
7
7
  gem.version = WeightedShuffle::VERSION
8
8
  gem.summary = %q{Fisher-Yates-Shuffle algorithm with weight support}
9
9
  gem.description = <<-EOF
10
- An extension to the Fisher-Yates-Shuffle algorithm to support weights. It
10
+ An extension to the Fisher-Yates-Shuffle algorithm to support weights. It
11
11
  includes a ruby core extension for arrays.
12
12
  EOF
13
13
  gem.license = "MIT"
@@ -26,4 +26,9 @@ Gem::Specification.new do |gem|
26
26
  gem.add_development_dependency 'simplecov'
27
27
  gem.add_development_dependency 'coveralls'
28
28
  gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
29
+
30
+ if ENV['RUBY_VERSION'] =~ /rbx/
31
+ gem.add_dependency 'rubysl'
32
+ gem.add_development_dependency 'rubinius-coverage'
33
+ end
29
34
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: weighted_shuffle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-07-09 00:00:00.000000000 Z
12
+ date: 2014-01-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -92,7 +92,7 @@ dependencies:
92
92
  - !ruby/object:Gem::Version
93
93
  version: '0.2'
94
94
  description: ! " An extension to the Fisher-Yates-Shuffle algorithm to support weights.
95
- \ It\n includes a ruby core extension for arrays.\n"
95
+ It\n includes a ruby core extension for arrays.\n"
96
96
  email: frank.eckert@boost-project.com
97
97
  executables: []
98
98
  extensions: []
@@ -103,7 +103,6 @@ files:
103
103
  - .rspec
104
104
  - .travis.yml
105
105
  - Gemfile
106
- - Gemfile.lock
107
106
  - LICENSE.txt
108
107
  - README.md
109
108
  - Rakefile
@@ -136,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
136
135
  version: '0'
137
136
  requirements: []
138
137
  rubyforge_project:
139
- rubygems_version: 1.8.24
138
+ rubygems_version: 1.8.23
140
139
  signing_key:
141
140
  specification_version: 3
142
141
  summary: Fisher-Yates-Shuffle algorithm with weight support
@@ -1,49 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- weighted_shuffle (0.1.0)
5
- activesupport
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- activesupport (3.2.13)
11
- i18n (= 0.6.1)
12
- multi_json (~> 1.0)
13
- colorize (0.5.8)
14
- coveralls (0.6.7)
15
- colorize
16
- multi_json (~> 1.3)
17
- rest-client
18
- simplecov (>= 0.7)
19
- thor
20
- diff-lcs (1.2.4)
21
- i18n (0.6.1)
22
- mime-types (1.23)
23
- multi_json (1.7.6)
24
- rest-client (1.6.7)
25
- mime-types (>= 1.16)
26
- rspec (2.13.0)
27
- rspec-core (~> 2.13.0)
28
- rspec-expectations (~> 2.13.0)
29
- rspec-mocks (~> 2.13.0)
30
- rspec-core (2.13.1)
31
- rspec-expectations (2.13.0)
32
- diff-lcs (>= 1.1.3, < 2.0)
33
- rspec-mocks (2.13.1)
34
- rubygems-tasks (0.2.4)
35
- simplecov (0.7.1)
36
- multi_json (~> 1.0)
37
- simplecov-html (~> 0.7.1)
38
- simplecov-html (0.7.1)
39
- thor (0.18.1)
40
-
41
- PLATFORMS
42
- ruby
43
-
44
- DEPENDENCIES
45
- coveralls
46
- rspec (~> 2.4)
47
- rubygems-tasks (~> 0.2)
48
- simplecov
49
- weighted_shuffle!