pickup 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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