Comment créer une liste de nombres aléatoires sans doublons?

110

J'ai essayé d'utiliser random.randint(0, 100), mais certains chiffres étaient les mêmes. Existe-t-il une méthode / un module pour créer une liste de nombres aléatoires uniques?

Remarque: Le code suivant est basé sur une réponse et a été ajouté après la publication de la réponse. Cela ne fait pas partie de la question; c'est la solution.

def getScores():
    # open files to read and write
    f1 = open("page.txt", "r");
    p1 = open("pgRes.txt", "a");

    gScores = [];
    bScores = [];
    yScores = [];

    # run 50 tests of 40 random queries to implement "bootstrapping" method 
    for i in range(50):
        # get 40 random queries from the 50
        lines = random.sample(f1.readlines(), 40);
iCodeLikeImDrunk
la source
1
S'ils sont uniques, ils peuvent être vraiment aléatoires dans le bon contexte. Comme un échantillon aléatoire d'index sans remplacement peut encore être complètement aléatoire.
gbtimmon le

Réponses:

180

Cela renverra une liste de 10 numéros sélectionnés dans la plage de 0 à 99, sans doublons.

import random
random.sample(range(100), 10)

En référence à votre exemple de code spécifique, vous souhaiterez probablement lire toutes les lignes du fichier une fois , puis sélectionner des lignes aléatoires dans la liste enregistrée en mémoire. Par exemple:

all_lines = f1.readlines()
for i in range(50):
    lines = random.sample(all_lines, 40)

De cette façon, vous n'avez besoin de lire le fichier qu'une seule fois, avant votre boucle. Il est beaucoup plus efficace de faire cela que de chercher au début du fichier et de le rappeler f1.readlines()à chaque itération de boucle.

Greg Hewgill
la source
2
Cette technique gaspille de la mémoire, en particulier pour les grands échantillons. J'ai posté ci-dessous le code pour une solution beaucoup plus efficace de mémoire et de calcul qui utilise un générateur linéaire congruentiel.
Thomas Lux
On m'a fait remarquer que la méthode LCG est cependant moins "aléatoire", donc si vous voulez générer de nombreuses séquences aléatoires uniques, la variété sera inférieure à cette solution. Si vous n'avez besoin que d'une poignée de séquences aléatoires, LCG est la voie à suivre!
Thomas Lux
Merci Greg, c'était utile
N Sivaram
15

Vous pouvez utiliser la lecture aléatoire fonction du hasard tel module:

import random

my_list = list(xrange(1,100)) # list of integers from 1 to 99
                              # adjust this boundaries to fit your needs
random.shuffle(my_list)
print my_list # <- List of unique random numbers

Notez ici que la méthode shuffle ne renvoie aucune liste comme on peut s'y attendre, elle ne fait que mélanger la liste passée par référence.

Ricardo Murillo
la source
Il est bon de mentionner ici que xrange ne fonctionne qu'en Python 2 et non en Python 3.
Shayan Shafiq
10

Vous pouvez d'abord créer une liste de nombres de aà b, où aet bsont respectivement les plus petits et les plus grands nombres de votre liste, puis la mélanger avec l' algorithme de Fisher-Yates ou en utilisant la random.shuffleméthode de Python .

ben
la source
1
Générer une liste complète d'indices est un gaspillage de mémoire, en particulier pour les grands échantillons. J'ai posté ci-dessous le code pour une solution beaucoup plus efficace de mémoire et de calcul qui utilise un générateur linéaire congruentiel.
Thomas Lux
8

La solution présentée dans cette réponse fonctionne, mais elle pourrait devenir problématique avec la mémoire si la taille de l'échantillon est petite, mais la population est énorme (par exemple random.sample(insanelyLargeNumber, 10)).

Pour résoudre ce problème, j'irais avec ceci:

answer = set()
sampleSize = 10
answerSize = 0

while answerSize < sampleSize:
    r = random.randint(0,100)
    if r not in answer:
        answerSize += 1
        answer.add(r)

# answer now contains 10 unique, random integers from 0.. 100
inspecteurG4dget
la source
random.sampleUtilise maintenant cette approche pour un petit nombre d'échantillons provenant d'une grande population, donc ce problème de mémoire n'existe plus vraiment. Bien qu'au moment où cette réponse a été rédigée, la mise en œuvre de random.shufflepeut avoir été différente.
kyrill le
5

Générateur de nombres pseudo-aléatoires congruentiels linéaires

O (1) Mémoire

O (k) Opérations

Ce problème peut être résolu avec un simple générateur congruentiel linéaire . Cela nécessite une surcharge de mémoire constante (8 entiers) et au plus 2 * (longueur de séquence) calculs.

Toutes les autres solutions utilisent plus de mémoire et plus de calcul! Si vous n'avez besoin que de quelques séquences aléatoires, cette méthode sera nettement moins chère. Pour les plages de taille N, si vous souhaitez générer de l'ordre de séquences Nuniques kou plus, je recommande la solution acceptée en utilisant les méthodes intégrées random.sample(range(N),k)car elle a été optimisée en python pour la vitesse.

Code

# Return a randomized "range" using a Linear Congruential Generator
# to produce the number sequence. Parameters are the same as for 
# python builtin "range".
#   Memory  -- storage for 8 integers, regardless of parameters.
#   Compute -- at most 2*"maximum" steps required to generate sequence.
#
def random_range(start, stop=None, step=None):
    import random, math
    # Set a default values the same way "range" does.
    if (stop == None): start, stop = 0, start
    if (step == None): step = 1
    # Use a mapping to convert a standard range into the desired range.
    mapping = lambda i: (i*step) + start
    # Compute the number of numbers in this range.
    maximum = (stop - start) // step
    # Seed range with a random integer.
    value = random.randint(0,maximum)
    # 
    # Construct an offset, multiplier, and modulus for a linear
    # congruential generator. These generators are cyclic and
    # non-repeating when they maintain the properties:
    # 
    #   1) "modulus" and "offset" are relatively prime.
    #   2) ["multiplier" - 1] is divisible by all prime factors of "modulus".
    #   3) ["multiplier" - 1] is divisible by 4 if "modulus" is divisible by 4.
    # 
    offset = random.randint(0,maximum) * 2 + 1      # Pick a random odd-valued offset.
    multiplier = 4*(maximum//4) + 1                 # Pick a multiplier 1 greater than a multiple of 4.
    modulus = int(2**math.ceil(math.log2(maximum))) # Pick a modulus just big enough to generate all numbers (power of 2).
    # Track how many random numbers have been returned.
    found = 0
    while found < maximum:
        # If this is a valid value, yield it in generator fashion.
        if value < maximum:
            found += 1
            yield mapping(value)
        # Calculate the next value in the sequence.
        value = (value*multiplier + offset) % modulus

Usage

L'utilisation de cette fonction "random_range" est la même que pour n'importe quel générateur (comme "range"). Un exemple:

# Show off random range.
print()
for v in range(3,6):
    v = 2**v
    l = list(random_range(v))
    print("Need",v,"found",len(set(l)),"(min,max)",(min(l),max(l)))
    print("",l)
    print()

Exemples de résultats

Required 8 cycles to generate a sequence of 8 values.
Need 8 found 8 (min,max) (0, 7)
 [1, 0, 7, 6, 5, 4, 3, 2]

Required 16 cycles to generate a sequence of 9 values.
Need 9 found 9 (min,max) (0, 8)
 [3, 5, 8, 7, 2, 6, 0, 1, 4]

Required 16 cycles to generate a sequence of 16 values.
Need 16 found 16 (min,max) (0, 15)
 [5, 14, 11, 8, 3, 2, 13, 1, 0, 6, 9, 4, 7, 12, 10, 15]

Required 32 cycles to generate a sequence of 17 values.
Need 17 found 17 (min,max) (0, 16)
 [12, 6, 16, 15, 10, 3, 14, 5, 11, 13, 0, 1, 4, 8, 7, 2, ...]

Required 32 cycles to generate a sequence of 32 values.
Need 32 found 32 (min,max) (0, 31)
 [19, 15, 1, 6, 10, 7, 0, 28, 23, 24, 31, 17, 22, 20, 9, ...]

Required 64 cycles to generate a sequence of 33 values.
Need 33 found 33 (min,max) (0, 32)
 [11, 13, 0, 8, 2, 9, 27, 6, 29, 16, 15, 10, 3, 14, 5, 24, ...]
Thomas Lux
la source
1
C'est très cool! Mais je suis sûr que cela répond vraiment à la question; disons que je veux échantillonner 2 valeurs de 0 à 4. Sans générer la mienne prime, la fonction ne me renverra que 4 réponses possibles, car valuec'est la seule chose choisie au hasard avec 4 valeurs possibles, lorsque nous avons besoin d'au moins (4 en choisir 2) = 6, (permettant un ordre non aléatoire). random_range(2,4)renverra les valeurs {(1, 0), (3, 2), (2, 1), (0, 3)}, mais jamais la paire (3,1) (ou (1,3)). Attendez-vous de nouveaux grands nombres premiers générés aléatoirement à chaque appel de fonction?
wowserx
1
(Je suppose également que vous vous attendez à ce que les gens mélangent la séquence après que votre fonction l'ait renvoyée s'ils veulent un ordre aléatoire, car random_range(v)retourne à vdes séquences uniques au lieu de v!)
wowserx
Totalement vrai! Il est difficile d'équilibrer entre éviter le débordement d'entiers et générer suffisamment de séquences aléatoires. J'ai mis à jour la fonction pour incorporer un peu plus d'aléatoire, mais ce n'est toujours pas aussi aléatoire que v !. Cela dépend si vous souhaitez utiliser la fonction plusieurs fois. Cette solution est mieux utilisée lorsque vous générez à partir d'une large plage de valeurs (lorsque la consommation de mémoire des autres serait beaucoup plus élevée). J'y réfléchirai plus, merci!
Thomas Lux
4

Si la liste de N nombres de 1 à N est générée aléatoirement, alors oui, il y a une possibilité que certains nombres puissent être répétés.

Si vous voulez une liste de nombres de 1 à N dans un ordre aléatoire, remplissez un tableau avec des entiers de 1 à N, puis utilisez un mélange Fisher-Yates ou Python random.shuffle().

Blé Mitch
la source
3

Si vous devez échantillonner des nombres extrêmement grands, vous ne pouvez pas utiliser range

random.sample(range(10000000000000000000000000000000), 10)

car il jette:

OverflowError: Python int too large to convert to C ssize_t

De plus, si random.samplevous ne pouvez pas produire le nombre d'articles que vous souhaitez en raison de la plage trop petite

 random.sample(range(2), 1000)

il jette:

 ValueError: Sample larger than population

Cette fonction résout les deux problèmes:

import random

def random_sample(count, start, stop, step=1):
    def gen_random():
        while True:
            yield random.randrange(start, stop, step)

    def gen_n_unique(source, n):
        seen = set()
        seenadd = seen.add
        for i in (i for i in source() if i not in seen and not seenadd(i)):
            yield i
            if len(seen) == n:
                break

    return [i for i in gen_n_unique(gen_random,
                                    min(count, int(abs(stop - start) / abs(step))))]

Utilisation avec des nombres extrêmement grands:

print('\n'.join(map(str, random_sample(10, 2, 10000000000000000000000000000000))))

Exemple de résultat:

7822019936001013053229712669368
6289033704329783896566642145909
2473484300603494430244265004275
5842266362922067540967510912174
6775107889200427514968714189847
9674137095837778645652621150351
9969632214348349234653730196586
1397846105816635294077965449171
3911263633583030536971422042360
9864578596169364050929858013943

Utilisation où la plage est inférieure au nombre d'éléments demandés:

print(', '.join(map(str, random_sample(100000, 0, 3))))

Exemple de résultat:

2, 0, 1

Il fonctionne également avec des plages et des étapes négatives:

print(', '.join(map(str, random_sample(10, 10, -10, -2))))
print(', '.join(map(str, random_sample(10, 5, -5, -2))))

Exemples de résultats:

2, -8, 6, -2, -4, 0, 4, 10, -6, 8
-3, 1, 5, -1, 3
Artisan
la source
Et si vous générez plus de 8 milliards de nombres, tôt ou tard, ils deviendront trop gros
david_adler
Cette réponse présente un grave défaut pour les grands échantillons. La probabilité de collision croît linéairement à chaque pas. J'ai publié une solution utilisant un générateur congruentiel linéaire qui a une surcharge de mémoire O (1) et des étapes O (k) requises pour générer des nombres k. Cela peut être résolu beaucoup plus efficacement!
Thomas Lux
Cette réponse est certainement meilleure si vous souhaitez générer un certain nombre de séquences aléatoires de l'ordre de la longueur de la séquence! La méthode LCG est moins «aléatoire» lorsqu'il s'agit de générer plusieurs séquences uniques.
Thomas Lux
"Cette fonction résout les deux problèmes" Comment résout-elle le deuxième problème? Vous ne pouvez toujours pas prélever 1 000 échantillons sur une population de 2. Au lieu de lancer une exception, vous produisez un résultat incorrect; ce n'est guère une résolution du "problème" (ce qui n'est vraiment pas un problème au départ puisqu'il n'est pas du tout raisonnable de demander k échantillons uniques à une population de n <k ).
kyrill le
1

Vous pouvez utiliser la bibliothèque Numpy pour une réponse rapide comme indiqué ci-dessous -

L'extrait de code donné répertorie 6 numéros uniques compris entre 0 et 5. Vous pouvez ajuster les paramètres pour votre confort.

import numpy as np
import random
a = np.linspace( 0, 5, 6 )
random.shuffle(a)
print(a)

Production

[ 2.  1.  5.  3.  4.  0.]

Il ne met aucune contrainte comme nous le voyons dans random.sample comme indiqué ici .

J'espère que ça aide un peu.

donnéesLeo
la source
1

La réponse fournie ici fonctionne très bien en ce qui concerne le temps ainsi que la mémoire mais un peu plus compliquée car elle utilise des constructions python avancées telles que yield. La réponse la plus simple fonctionne bien dans la pratique, mais le problème avec cette réponse est qu'elle peut générer de nombreux entiers faux avant de construire réellement l'ensemble requis. Essayez-le avec populationSize = 1000, sampleSize = 999. En théorie, il y a une chance qu'il ne se termine pas.

La réponse ci-dessous aborde les deux problèmes, car elle est déterministe et quelque peu efficace bien qu'elle ne soit actuellement pas aussi efficace que les deux autres.

def randomSample(populationSize, sampleSize):
  populationStr = str(populationSize)
  dTree, samples = {}, []
  for i in range(sampleSize):
    val, dTree = getElem(populationStr, dTree, '')
    samples.append(int(val))
  return samples, dTree

où les fonctions getElem, percolateUp sont telles que définies ci-dessous

import random

def getElem(populationStr, dTree, key):
  msd  = int(populationStr[0])
  if not key in dTree.keys():
    dTree[key] = range(msd + 1)
  idx = random.randint(0, len(dTree[key]) - 1)
  key = key +  str(dTree[key][idx])
  if len(populationStr) == 1:
    dTree[key[:-1]].pop(idx)
    return key, (percolateUp(dTree, key[:-1]))
  newPopulation = populationStr[1:]
  if int(key[-1]) != msd:
    newPopulation = str(10**(len(newPopulation)) - 1)
  return getElem(newPopulation, dTree, key)

def percolateUp(dTree, key):
  while (dTree[key] == []):
    dTree[key[:-1]].remove( int(key[-1]) )
    key = key[:-1]
  return dTree

Enfin, le timing en moyenne était d'environ 15ms pour une grande valeur de n comme indiqué ci-dessous,

In [3]: n = 10000000000000000000000000000000

In [4]: %time l,t = randomSample(n, 5)
Wall time: 15 ms

In [5]: l
Out[5]:
[10000000000000000000000000000000L,
 5731058186417515132221063394952L,
 85813091721736310254927217189L,
 6349042316505875821781301073204L,
 2356846126709988590164624736328L]
aak318
la source
Vous pensez que cette réponse est compliquée? Qu'est-ce que c'est alors?! Et puis il y a l' autre réponse , qui génère de nombreux "entiers faux". J'ai exécuté votre implémentation avec l'exemple d'entrée que vous avez donné (populationSize = 1000, sampleSize = 999). Votre version appelle la random.randintfonction 3996 fois, tandis que l'autre cca. 6000 fois. Pas une si grande amélioration, hein?
kyrill le
@kyrill, votre opinion sur cette réponse
aak318
1

Afin d'obtenir un programme qui génère une liste de valeurs aléatoires sans doublons qui soit déterministe, efficace et construit avec des constructions de programmation de base, considérez la fonction extractSamplesdéfinie ci-dessous,

def extractSamples(populationSize, sampleSize, intervalLst) :
    import random
    if (sampleSize > populationSize) :
        raise ValueError("sampleSize = "+str(sampleSize) +" > populationSize (= " + str(populationSize) + ")")
    samples = []
    while (len(samples) < sampleSize) :
        i = random.randint(0, (len(intervalLst)-1))
        (a,b) = intervalLst[i]
        sample = random.randint(a,b)
        if (a==b) :
            intervalLst.pop(i)
        elif (a == sample) : # shorten beginning of interval                                                                                                                                           
            intervalLst[i] = (sample+1, b)
        elif ( sample == b) : # shorten interval end                                                                                                                                                   
            intervalLst[i] = (a, sample - 1)
        else :
            intervalLst[i] = (a, sample - 1)
            intervalLst.append((sample+1, b))
        samples.append(sample)
    return samples

L'idée de base est de garder une trace des intervalles intervalLstpour les valeurs possibles à partir desquelles sélectionner nos éléments requis. Ceci est déterministe dans le sens où nous sommes assurés de générer un échantillon en un nombre fixe d'étapes (dépendant uniquement de populationSizeet sampleSize).

Pour utiliser la fonction ci-dessus pour générer notre liste requise,

In [3]: populationSize, sampleSize = 10**17, 10**5

In [4]: %time lst1 = extractSamples(populationSize, sampleSize, [(0, populationSize-1)])
CPU times: user 289 ms, sys: 9.96 ms, total: 299 ms
Wall time: 293 ms

On peut aussi comparer avec une solution antérieure (pour une valeur inférieure de populationSize)

In [5]: populationSize, sampleSize = 10**8, 10**5

In [6]: %time lst = random.sample(range(populationSize), sampleSize)
CPU times: user 1.89 s, sys: 299 ms, total: 2.19 s
Wall time: 2.18 s

In [7]: %time lst1 = extractSamples(populationSize, sampleSize, [(0, populationSize-1)])
CPU times: user 449 ms, sys: 8.92 ms, total: 458 ms
Wall time: 442 ms

Notez que j'ai réduit la populationSizevaleur car cela produit une erreur de mémoire pour des valeurs plus élevées lors de l'utilisation de la random.samplesolution (également mentionné dans les réponses précédentes ici et ici ). Pour les valeurs ci-dessus, nous pouvons également observer que extractSamplessurpasse l' random.sampleapproche.

PS: Bien que l'approche de base soit similaire à ma réponse précédente , il y a des modifications substantielles dans la mise en œuvre ainsi que l'approche avec une amélioration de la clarté.

aak318
la source
0

Une fonction très simple qui résout également votre problème

from random import randint

data = []

def unique_rand(inicial, limit, total):

        data = []

        i = 0

        while i < total:
            number = randint(inicial, limit)
            if number not in data:
                data.append(number)
                i += 1

        return data


data = unique_rand(1, 60, 6)

print(data)


"""

prints something like 

[34, 45, 2, 36, 25, 32]

"""
Vinicius Torino
la source
0

Le problème avec les approches basées sur les ensembles ("si une valeur aléatoire dans les valeurs de retour, essayez à nouveau") est que leur durée d'exécution est indéterminée en raison de collisions (qui nécessitent une autre itération "réessayer"), en particulier lorsqu'une grande quantité de valeurs aléatoires est renvoyée de la gamme.

Une alternative qui n'est pas sujette à ce runtime non déterministe est la suivante:

import bisect
import random

def fast_sample(low, high, num):
    """ Samples :param num: integer numbers in range of
        [:param low:, :param high:) without replacement
        by maintaining a list of ranges of values that
        are permitted.

        This list of ranges is used to map a random number
        of a contiguous a range (`r_n`) to a permissible
        number `r` (from `ranges`).
    """
    ranges = [high]
    high_ = high - 1
    while len(ranges) - 1 < num:
        # generate a random number from an ever decreasing
        # contiguous range (which we'll map to the true
        # random number).
        # consider an example with low=0, high=10,
        # part way through this loop with:
        #
        # ranges = [0, 2, 3, 7, 9, 10]
        #
        # r_n :-> r
        #   0 :-> 1
        #   1 :-> 4
        #   2 :-> 5
        #   3 :-> 6
        #   4 :-> 8
        r_n = random.randint(low, high_)
        range_index = bisect.bisect_left(ranges, r_n)
        r = r_n + range_index
        for i in xrange(range_index, len(ranges)):
            if ranges[i] <= r:
                # as many "gaps" we iterate over, as much
                # is the true random value (`r`) shifted.
                r = r_n + i + 1
            elif ranges[i] > r_n:
                break
        # mark `r` as another "gap" of the original
        # [low, high) range.
        ranges.insert(i, r)
        # Fewer values possible.
        high_ -= 1
    # `ranges` happens to contain the result.
    return ranges[:-1]
Orange
la source
0
import random

sourcelist=[]
resultlist=[]

for x in range(100):
    sourcelist.append(x)

for y in sourcelist:
    resultlist.insert(random.randint(0,len(resultlist)),y)

print (resultlist)
user85510
la source
1
Bienvenue dans Stackoverflow. Veuillez expliquer votre réponse pourquoi et comment résout-elle le problème afin que les autres puissent comprendre votre réponse facilement.
octobus
Bien que ce code puisse résoudre la question, inclure une explication sur comment et pourquoi cela résout le problème aiderait vraiment à améliorer la qualité de votre message et entraînerait probablement plus de votes à la hausse. N'oubliez pas que vous répondez à la question des lecteurs à l'avenir, pas seulement à la personne qui la pose maintenant. Veuillez modifier votre réponse pour ajouter des explications et donner une indication des limites et des hypothèses applicables. De l'avis
double-beep
-1

Si vous souhaitez vous assurer que les numéros ajoutés sont uniques, vous pouvez utiliser un objet Set

si vous utilisez 2.7 ou supérieur, ou importez le module sets sinon.

Comme d'autres l'ont mentionné, cela signifie que les nombres ne sont pas vraiment aléatoires.

Recaiden
la source
-1

pour échantillonner des entiers sans remplacement entre minvalet maxval:

import numpy as np

minval, maxval, n_samples = -50, 50, 10
generator = np.random.default_rng(seed=0)
samples = generator.permutation(np.arange(minval, maxval))[:n_samples]

# or, if minval is 0,
samples = generator.permutation(maxval)[:n_samples]

avec jax:

import jax

minval, maxval, n_samples = -50, 50, 10
key = jax.random.PRNGKey(seed=0)
samples = jax.random.shuffle(key, jax.numpy.arange(minval, maxval))[:n_samples]
grisaitis
la source
Pourquoi généreriez-vous une permutaiton d'un nombre éventuellement important d'éléments et ne sélectionneriez-vous que le premier n_samplesd'entre eux? Quel est votre raisonnement derrière cette approche? Pouvez-vous expliquer quels sont les avantages de votre approche par rapport à l'un des nombreux réponses existantes (la plupart datant d'il y a 8 ans)?
kyrill le
en fait, ma réponse a une complexité similaire à celle des autres réponses les plus votées et est plus rapide car elle utilise numpy. d'autres méthodes, les plus votées random.shuffle, utilisent Mersenne Twister, qui est beaucoup plus lente que les algos proposés par numpy (et probablement jax). numpy et jax permettent d'autres algorithmes de génération de nombres aléatoires. jax permet également la compilation et la différenciation jit, ce qui peut être utile pour la différenciation stochastique. aussi, en ce qui concerne un tableau "peut-être grand", certaines réponses les plus votées font exactement la même chose avec random.shuffle, ce que je ne pense pas être un péché dans un sens relatif ou même absolu
grisaitis
1
Je ne sais pas ce que vous entendez par « random.shuffleutilise Mersenne Twister» - c'est le mélange Fisher-Yates, comme mentionné dans plusieurs réponses. Il a une complexité temporelle linéaire, il ne peut donc pas être asymptotiquement plus lent que les algorithmes proposés par toute autre bibliothèque, numpy ou autre. Si numpy est plus rapide, c'est uniquement parce qu'il est implémenté en C, mais cela ne justifie pas de générer une énorme permutation (une qui pourrait même ne pas tenir en mémoire), seulement pour en choisir quelques éléments. Il n'y a pas une seule réponse en dehors de la vôtre qui fasse cela.
kyrill
Mes excuses, j'ai lu que python aléatoire utilisait Mersenne Twister comme il est prng. Avez-vous une source pour que je puisse en savoir plus sur Fisher Yates et le rôle dans random.shuffle?
grisaitis
Il existe déjà deux liens distincts vers Wikipedia sur deux réponses distinctes ici. Si Wikipédia n'est pas une source suffisante pour vous, il y a 14 références à la fin de l'article. Et puis il y a Google. Est ce que ça aide? Oh, et le randommodule est écrit en Python, vous pouvez donc facilement voir sa source (essayez random.__file__).
kyrill
-3

À partir de la CLI dans win xp:

python -c "import random; print(sorted(set([random.randint(6,49) for i in range(7)]))[:6])"

Au Canada, nous avons le 6/49 Lotto. J'emballe juste le code ci-dessus dans lotto.bat et exécute C:\home\lotto.batou juste C:\home\lotto.

Parce que random.randintrépète souvent un nombre, je l'utilise setavec range(7), puis je le raccourcis à une longueur de 6.

Parfois, si un nombre se répète plus de 2 fois, la longueur de la liste résultante sera inférieure à 6.

EDIT: Cependant, random.sample(range(6,49),6)c'est la bonne voie à suivre.

exbctel
la source
-3
import random
result=[]
for i in range(1,50):
    rng=random.randint(1,20)
    result.append(rng)
user2904400
la source
1
Pouvez-vous expliquer comment cela évite les doublons? Ce n'est pas évident à partir de ce vidage de code.
Toby Speight
Ce n'est pas le cas. print len(result), len(set(result)). Vous vous attendriez à voir que resultcela aurait des éléments uniques une seule fois à chaque 1.0851831788708547256608362340568947172111832359638926... × 10^20essai.
Jedi