pickup 0.0.7 → 0.0.8

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/README.md CHANGED
@@ -92,6 +92,16 @@ pickup.pick(10){ |v| v**10 }
92
92
  #=> ["minnow", "minnow", "minnow", "minnow", "minnow", "minnow", "minnow", "minnow", "minnow", "minnow"]
93
93
  ```
94
94
 
95
+ Or you can use reverse probability:
96
+
97
+ ```ruby
98
+ pickup = Pickup.new(pond)
99
+ pickup.pick(10){ |v| v**(-10) }
100
+ #=> ["selmon", "selmon", "selmon", "selmon", "crucian", "selmon", "selmon", "selmon", "selmon", "selmon"]
101
+ ```
102
+
103
+ Reverse
104
+
95
105
  ## Contributing
96
106
 
97
107
  1. Fork it
@@ -0,0 +1,72 @@
1
+ require 'benchmark'
2
+ require './lib/pickup'
3
+
4
+ def simple_hash
5
+ @simple ||= begin
6
+ hash = {}
7
+ (1..30).to_a.each do |i|
8
+ hash["item_#{i}"] = rand(30)
9
+ end
10
+ hash
11
+ end
12
+ end
13
+
14
+ def big_hash
15
+ @big ||= begin
16
+ hash = {}
17
+ (1..5000).to_a.each do |i|
18
+ hash["item_#{i}"] = rand(1000)
19
+ end
20
+ hash
21
+ end
22
+ end
23
+
24
+ def big_weights_hash
25
+ @big_weights ||= begin
26
+ hash = {}
27
+ (1..5000).to_a.each do |i|
28
+ hash["item_#{i}"] = rand(100_000) + 10_000
29
+ end
30
+ hash
31
+ end
32
+ end
33
+
34
+ def simple(uniq=false)
35
+ pickup = Pickup.new(simple_hash, uniq: uniq)
36
+ pickup.pick(10)
37
+ end
38
+
39
+ def big(uniq=false)
40
+ pickup = Pickup.new(big_hash, uniq: uniq)
41
+ pickup.pick(100)
42
+ end
43
+
44
+ def big_weights(uniq=false)
45
+ pickup = Pickup.new(big_weights_hash, uniq: uniq)
46
+ pickup.pick(100)
47
+ end
48
+
49
+
50
+
51
+ n = 500
52
+
53
+ Benchmark.bm do |x|
54
+ x.report("simple: ") do
55
+ n.times{ simple }
56
+ end
57
+ x.report("simple uniq: ") do
58
+ n.times{ simple(true) }
59
+ end
60
+ x.report("big: ") do
61
+ n.times{ big }
62
+ end
63
+ x.report("big uniq: ") do
64
+ n.times{ big(true) }
65
+ end
66
+ x.report("big weights: ") do
67
+ n.times{ big_weights }
68
+ end
69
+ x.report("big weights uniq: ") do
70
+ n.times{ big_weights(true) }
71
+ end
72
+ end
@@ -26,31 +26,27 @@ class Pickup
26
26
  end
27
27
 
28
28
  class CircleIterator
29
- attr_reader :func, :obj
29
+ attr_reader :func, :obj, :max
30
30
 
31
- def initialize(obj, func)
31
+ def initialize(obj, func, max)
32
32
  @obj = obj.dup
33
33
  @func = func
34
+ @max = max
34
35
  end
35
36
 
36
37
  def each
37
- mx = max
38
38
  until obj.empty?
39
39
  start = 0
40
40
  obj.each do |item, weight|
41
41
  val = func.call(weight)
42
42
  start += val
43
- if yield([item, start, mx])
43
+ if yield([item, start, max])
44
44
  obj.delete item
45
- mx = max
45
+ @max -= val
46
46
  end
47
47
  end
48
48
  end
49
49
  end
50
-
51
- def max
52
- obj.inject(0){ |mx, item| mx += func.call(item[1]) }
53
- end
54
50
  end
55
51
 
56
52
  class MappedList
@@ -64,7 +60,7 @@ class Pickup
64
60
  end
65
61
 
66
62
  def each(&blk)
67
- CircleIterator.new(@list, func).each do |item|
63
+ CircleIterator.new(@list, func, max).each do |item|
68
64
  if uniq
69
65
  true if yield item
70
66
  else
@@ -80,14 +76,13 @@ class Pickup
80
76
  end
81
77
 
82
78
  def get_random_items(nums)
83
- next_num = Proc.new{ nums.shift }
84
- current_num = next_num.call
79
+ current_num = nums.shift
85
80
  items = []
86
81
  each do |item, counter, mx|
87
82
  break unless current_num
88
83
  if counter%(mx+1) > current_num%mx
89
84
  items << item
90
- current_num = next_num.call
85
+ current_num = nums.shift
91
86
  true
92
87
  end
93
88
  end
@@ -95,7 +90,11 @@ class Pickup
95
90
  end
96
91
 
97
92
  def max
98
- list.inject(0){ |mx, item| mx += func.call(item[1]) }
93
+ @max ||= begin
94
+ max = 0
95
+ list.each{ |item| max += func.call(item[1]) }
96
+ max
97
+ end
99
98
  end
100
99
  end
101
100
  end
@@ -1,3 +1,3 @@
1
1
  class Pickup
2
- VERSION = "0.0.7"
2
+ VERSION = "0.0.8"
3
3
  end
@@ -60,8 +60,13 @@ describe Pickup do
60
60
  proc{ items = @pickup2.pick(8) }.must_raise RuntimeError
61
61
  end
62
62
 
63
- it "should return include most wegtful item (but not always - sometimes it will fail)" do
63
+ it "should return include most weigtfull item (but not always - sometimes it will fail)" do
64
64
  items = @pickup2.pick(2){ |v| v**20 }
65
65
  (items.include? "minnow").must_equal true
66
66
  end
67
+
68
+ it "should return include less weigtfull item (but not always - sometimes it will fail)" do
69
+ items = @pickup2.pick(2){ |v| v**(-20) }
70
+ (items.include? "selmon").must_equal true
71
+ end
67
72
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pickup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -23,6 +23,7 @@ files:
23
23
  - LICENSE
24
24
  - README.md
25
25
  - Rakefile
26
+ - benchmarks/pickup.rb
26
27
  - lib/pickup.rb
27
28
  - lib/pickup/version.rb
28
29
  - pickup.gemspec