```In article <03fc01c2f5ba\$a04cb8e0\$0300a8c0 / austin.rr.com>,
Hal E. Fulton <hal9000 / hypermetrics.com> wrote:
>Here's a little question for you.
>
>Given: A set of items, each with
>an associated integer representing
>the relative likelihood that each
>item will be selected.
>
>Write: A method that will select
>a random item.
>
>I've started this a couple of times,
>but have become convinced I'm making
>it too hard, and someone can probably
>come up with a three-liner.
>
>Any ideas?
>

You're talking about some kind of proportional selection scheme (hey, you
wouldn't happen to be working on Genetic Algorithms, would you?).  One way
would be to do what's called roulette wheel selection.  You can visualize
a roulette wheel where each number is sized proportionally to the weight.
The bigger the weight, the more likely the 'roulette wheel' is to land on
that item.

It would look something like:

#Warning: untested code!
class RouletteWheel
def initialize(itemList)
@rouletteList = []
runningTotal = 0
@items = itemList
calc_sum
@items.each_with_index{ |w,i|
prob = calc_prob(w)
runningTotal += prob
@rouletteList[i] = runningTotal
}
end

def spin
rn = rand
prev = 0.0
@items.each_with_index { |w,i|
@rouletteList.each_with_index { |p,j|
if rn.between?(prev,p)
return @items[j]
end
prev = p
}
}
#otherwise return the last one:
return @items[-1]
end

private
def calc_sum
@items.each { |w|
@sum += w
}
end

def calc_prob(value)
value/@sum.to_f
end

end

#use it:

rw = RouletteWheel([10,20,3,42,121,5])
item = rw.spin #most likely to get 121, least likely to get 3

Or alternatively, you could have spin return the index of the item in the
array.

Now of course you'd probably modify it so that the itemList passed in
isn't just a list of integers, but objects which contain an integer
weighting....

Phil

```