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 +10 -0
- data/benchmarks/pickup.rb +72 -0
- data/lib/pickup.rb +13 -14
- data/lib/pickup/version.rb +1 -1
- data/spec/pickup/pickup_spec.rb +6 -1
- metadata +2 -1
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
|
data/lib/pickup.rb
CHANGED
@@ -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,
|
43
|
+
if yield([item, start, max])
|
44
44
|
obj.delete item
|
45
|
-
|
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
|
-
|
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 =
|
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
|
-
|
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
|
data/lib/pickup/version.rb
CHANGED
data/spec/pickup/pickup_spec.rb
CHANGED
@@ -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
|
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.
|
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
|