Choices randomly an element from a list, not uniformly, but using a given weight for each element.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | #!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import division
import random, bisect
class ItemGenerator(object):
'''Choices randomly an element from a list.
It does it not uniformly, but using a given weight for
each element.
Just instantiate this class passing a list of pairs
(item, weight), and then call it to get the items.
'''
def __init__(self, items):
self.puntos = []
self.ponderado = []
total = sum(x[1] for x in items)
acum = 0
for it,peso in items:
acum += peso
self.puntos.append(it)
self.ponderado.append(acum/total)
self.total = acum - 1
def __call__(self):
ind = random.random()
cual = bisect.bisect(self.ponderado, ind)
return self.puntos[cual]
if __name__ == "__main__":
# This shows the usage, and also test the recipe, as calling that
# a lot of times, it should return the elements in the same
# given proportion
items = (
("A", 10),
("B", 100),
("C", 5)
)
itgen = ItemGenerator(items)
cuenta = {}
for i in range(1000000):
item = itgen()
cuenta[item] = cuenta.get(item, 0) + 1
print cuenta
|
Tags: algorithms
Rosetta Code has a couple of solutions in Python, (by me), as well as many more in other languages.