I tried to write a weighted lottery drawing class in Ruby, and it proved useful to recursively instantiate the same class in any of its method definition:
class Weighted_draw
attr_accessor :elements_with_weights,:sum_of_weights,:sorted_elements_with_weights,
:elements_with_cumulated_weights
def initialize(w)
@sum_of_weights=w.map{|z| z[1]}.inject(:+)
if sum_of_weights != 1.0 then
@elements_with_weights=w.map{|z| [z[0],z[1].fdiv(sum_of_weights)]}
else
@elements_with_weights=w
end
@sorted_elements_with_weights=elements_with_weights.sort_by{|z| z[1]}
@elements_with_cumulated_weights=sorted_elements_with_weights.collect.with_index.map{|z,i| [z[0],sorted_elements_with_weights[0..i].map{|q| q[1]}.inject(:+)]}
end
def pick
r=rand
self.elements_with_cumulated_weights.find{|z| z[1]>=r}[0]
end
def pick_n(n)
if n>elements_with_weights.size then
return nil
else
ret=[]
wd=Weighted_draw.new(elements_with_weights)
for i in 1..n do
picked_element=wd.pick
ret.push picked_element
wd=Weighted_draw.new(elements_with_weights.reject{|z| z[0]==picked_element})
end
return ret.sort
end
end
end
end
Then I can use it as:
w=[[1,0.25],[2,0.1],[3,0.25],[4,0.1],[5,0.3]]
wd=Weighted_draw.new(w)
wd.pick_n(2)
Is it an allowed practise?
Aucun commentaire:
Enregistrer un commentaire