Je dois renvoyer des valeurs différentes basées sur un tournoi à la ronde pondéré de telle sorte que 1 sur 20 obtient A, 1 sur 20 obtient B, et le reste passe à C.
Alors:
A => 5%
B => 5%
C => 90%
Voici une version de base qui semble fonctionner:
import random
x = random.randint(1, 100)
if x <= 5:
return 'A'
Elif x > 5 and x <= 10:
return 'B'
else:
return 'C'
Cet algorithme est-il correct? Si oui, peut-il être amélioré?
Votre algorithme est correct, que diriez-vous de quelque chose de plus élégant:
import random
my_list = ['A'] * 5 + ['B'] * 5 + ['C'] * 90
random.choice(my_list)
c'est très bien. plus généralement, vous pouvez définir quelque chose comme:
from collections import Counter
from random import randint
def weighted_random(pairs):
total = sum(pair[0] for pair in pairs)
r = randint(1, total)
for (weight, value) in pairs:
r -= weight
if r <= 0: return value
results = Counter(weighted_random([(1,'a'),(1,'b'),(18,'c')])
for _ in range(20000))
print(results)
qui donne
Counter({'c': 17954, 'b': 1039, 'a': 1007})
qui est aussi proche de 18: 1: 1 que vous pouvez vous y attendre.
Si vous souhaitez utiliser un aléatoire pondéré et non un aléatoire centile, vous pouvez créer votre propre classe Randomizer:
import random
class WeightedRandomizer:
def __init__ (self, weights):
self.__max = .0
self.__weights = []
for value, weight in weights.items ():
self.__max += weight
self.__weights.append ( (self.__max, value) )
def random (self):
r = random.random () * self.__max
for ceil, value in self.__weights:
if ceil > r: return value
w = {'A': 1.0, 'B': 1.0, 'C': 18.0}
#or w = {'A': 5, 'B': 5, 'C': 90}
#or w = {'A': 1.0/18, 'B': 1.0/18, 'C': 1.0}
#or or or
wr = WeightedRandomizer (w)
results = {'A': 0, 'B': 0, 'C': 0}
for i in range (10000):
results [wr.random () ] += 1
print ('After 10000 rounds the distribution is:')
print (results)
Cela semble correct puisque vous utilisez une variable aléatoire uniform
avec des tirages indépendants, la probabilité pour chaque nombre sera 1/n
(n = 100).
Vous pouvez facilement vérifier votre algorithme en l'exécutant par exemple 1000 fois et voir la fréquence de chaque lettre.
Un autre algorithme que vous pourriez envisager est de générer un tableau avec vos lettres en fonction de la fréquence que vous souhaitez pour chaque lettre et de générer uniquement un nombre aléatoire unique qui est l'indice dans le tableau
Il sera moins efficace en mémoire mais devrait mieux fonctionner
Modifier:
Pour répondre au commentaire de @Joel Cornett, un exemple sera très similaire à @jurgenreza mais plus efficace en mémoire
import random
data_list = ['A'] + ['B'] + ['C'] * 18
random.choice(data_list )