Як створити список випадкових чисел без дублікатів?


110

Я спробував використовувати random.randint(0, 100), але деякі цифри були однакові. Чи існує метод / модуль для створення списку унікальних випадкових чисел?

Примітка. Наступний код заснований на відповіді та був доданий після публікації відповіді. Це не частина питання; це рішення.

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);

1
Якщо вони унікальні, вони можуть бути справді випадковими в правильному контексті. Як і випадкова вибірка індексів без заміни все ще може бути повністю випадковою.
gbtimmon

Відповіді:


180

Це поверне список із 10 чисел, вибраних у діапазоні від 0 до 99, без дублікатів.

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

Посилаючись на ваш конкретний приклад коду, ви, ймовірно, хочете прочитати всі рядки з файлу один раз, а потім вибрати випадкові рядки зі збереженого списку в пам'яті. Наприклад:

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

Таким чином, вам потрібно прочитати з файлу лише один раз, перед циклом. Це зробити набагато ефективніше, ніж повернутися до початку файлу та f1.readlines()знову зателефонувати за кожну ітерацію циклу.


2
Ця методика витрачає пам'ять, особливо для великих зразків. Нижче я розмістив код для набагато більшого обсягу пам'яті та обчислення ефективного рішення, в якому використовується лінійний конгрурентний генератор.
Томас Люкс

Мені було вказано, що метод LCG менш "випадковий", тому, якщо ви хочете створити багато унікальних випадкових послідовностей, різноманітність буде меншою, ніж це рішення. Якщо вам потрібна лише кілька випадкових послідовностей, LCG - це шлях!
Томас Люкс

Дякую, Грег, це було корисно
N Sivaram

15

Ви можете використовувати функцію переміщення з випадкового модуля, як це:

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

Зауважте тут, що метод перетасування не повертає жодного списку, як можна було очікувати, він переміщує лише перетасований список, переданий посиланням.


Тут добре згадати, що xrange працює лише в Python 2, а не в Python 3.
Shayan Shafiq

10

Спочатку можна створити список чисел від aдо b, де aі b, відповідно, найменші та найбільші числа у вашому списку, а потім перемістити його за допомогою алгоритму Фішера-Йейта або за допомогою random.shuffleметоду Python .


1
Створення повного списку індексів є марною пам'яттю, особливо для великих зразків. Нижче я розмістив код для набагато більше пам'яті та обчислення ефективного рішення, в якому використовується лінійний конгрурентний генератор.
Томас Люкс

8

Рішення, представлене у цій відповіді, працює, але це може стати проблематичним для пам'яті, якщо розмір вибірки невеликий, але кількість населення величезна (наприклад,random.sample(insanelyLargeNumber, 10) ).

Щоб виправити це, я б пішов із цим:

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

Зараз random.sampleцей підхід використовується для невеликої кількості зразків з великої сукупності, тому ця проблема з пам'яттю вже не існує. Хоча, на момент написання цієї відповіді, реалізація random.shuffleможливо була різною.
kyrill

5

Генератор лінійного конгрурентного псевдовипадкового числа

O (1) Пам'ять

O (k) Операції

Цю проблему можна вирішити за допомогою простого лінійного конгрурентного генератора . Для цього потрібні постійні накладні оперативні пам'яті (8 цілих чисел) і не більше 2 * (довжина послідовності).

Всі інші рішення використовують більше пам'яті та більше обчислень! Якщо вам потрібно лише кілька випадкових послідовностей, цей спосіб буде значно дешевшим. Для діапазонів розмірів N, якщо ви хочете генерувати в порядку Nунікальних kнаслідків або більше, я рекомендую прийняте рішення, використовуючи вбудовані методи, random.sample(range(N),k)оскільки це було оптимізовано в python для швидкості.

Код

# 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

Використання

Використання цієї функції "random_range" така ж, як і для будь-якого генератора (наприклад, "діапазон"). Приклад:

# 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()

Зразкові результати

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, ...]

1
Це дуже круто! Але я впевнений, що це дійсно відповідає на питання; скажіть, я хочу пробити 2 значення від 0 до 4. Не генеруючи власних prime, функція поверне мені лише 4 можливі відповіді, оскільки valueце єдина випадково обрана річ із 4 можливими значеннями, коли нам потрібно щонайменше (4 виберіть 2) = 6, (з урахуванням випадкового впорядкування). random_range(2,4)поверне значення {(1, 0), (3, 2), (2, 1), (0, 3)}, але ніколи не пара (3,1) (або (1,3)). Чи очікуєте ви нових випадково згенерованих великих простих чисел кожного виклику функції?
wowserx

1
(Також я припускаю, що ви очікуєте, що люди змішать послідовність після того, як ваша функція поверне її, якщо вони хочуть випадкового впорядкування, оскільки замість них random_range(v)повертається до vунікальних послідовностей v!)
wowserx

Цілком правда! Важко балансувати між уникненням цілочислового переливу та генеруванням достатньої кількості випадкових послідовностей. Я оновив функцію, щоб включити трохи більше випадковості, але вона все ще не така випадкова, як v !. Це залежить від того, чи потрібно використовувати функцію кілька разів. Це рішення найкраще використовувати, коли ви генеруєте з великого діапазону значень (коли споживання пам'яті інших було б набагато вище). Я подумаю над цим більше, дякую!
Томас Люкс

4

Якщо список N чисел від 1 до N генерується випадковим чином, то так, існує ймовірність, що деякі числа можуть бути повторені.

Якщо ви хочете, щоб список чисел від 1 до N був у випадковому порядку, заповніть масив цілими числами від 1 до N, а потім використовуйте переміщення Fisher-Yates або Python's random.shuffle().


3

Якщо вам потрібно взяти вибірку надзвичайно великої кількості, ви не можете використовувати range

random.sample(range(10000000000000000000000000000000), 10)

тому що це кидає:

OverflowError: Python int too large to convert to C ssize_t

Крім того, якщо random.sampleви не можете створити потрібну кількість предметів через занадто малий діапазон

 random.sample(range(2), 1000)

він кидає:

 ValueError: Sample larger than population

Ця функція вирішує обидві проблеми:

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))))]

Використання з надзвичайно великою кількістю:

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

Зразок результату:

7822019936001013053229712669368
6289033704329783896566642145909
2473484300603494430244265004275
5842266362922067540967510912174
6775107889200427514968714189847
9674137095837778645652621150351
9969632214348349234653730196586
1397846105816635294077965449171
3911263633583030536971422042360
9864578596169364050929858013943

Використання, коли діапазон менший, ніж кількість запитуваних елементів:

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

Зразок результату:

2, 0, 1

Він також працює з негативними діапазонами та кроками:

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

Приклад результатів:

2, -8, 6, -2, -4, 0, 4, 10, -6, 8
-3, 1, 5, -1, 3

що, якщо ви генеруєте понад 8 мільярдів чисел, рано чи пізно побачене стане занадто великим
david_adler

Ця відповідь має серйозний недолік для великих зразків. Імовірність зіткнення зростає лінійно з кожним кроком. Я розмістив рішення, використовуючи лінійний генератор конгрегенції, у якого є O (1) накладні пам'яті та O (k) кроки, необхідні для генерації k чисел. Це можна вирішити набагато ефективніше!
Томас Люкс

Ця відповідь, безумовно, краща, якщо ви хочете генерувати кількість випадкових послідовностей на порядок довжини послідовності! Метод LCG менш "випадковий", коли мова йде про генерацію декількох унікальних послідовностей.
Томас Люкс

"Ця функція вирішує обидві проблеми" Як вона вирішує другу проблему? Ви все ще не можете взяти 1000 зразків з популяції 2. Замість того, щоб викидати виняток, ви даєте неправильний результат; це навряд чи є вирішенням "проблеми" (що насправді не є проблемою для початку, оскільки зовсім не розумно вимагати k унікальних зразків від популяції n <k ).
kyrill

1

Ви можете використовувати бібліотеку Numpy для швидкої відповіді, як показано нижче -

Наведений фрагмент коду перераховує 6 унікальних номерів між діапазоном від 0 до 5. Ви можете налаштувати параметри для свого комфорту.

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

Вихід

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

Він не ставить обмежень, як ми бачимо у random.sample, про який йдеться тут .

Сподіваюсь, це трохи допомагає.


1

Відповідь, надана тут, працює дуже добре щодо часу, а також пам’яті, але трохи складніше, оскільки використовує вдосконалені конструкції пітона, такі як урожайність. простіше відповідь добре працює на практиці , але, питання з цією відповіддю є те , що він може генерувати багато хибних чисел до фактичного побудови необхідного набору. Спробуйте це з popuSize = 1000, sampleSize = 999. Теоретично є ймовірність, що воно не закінчиться.

Відповідь нижче стосується обох питань, оскільки вона є детермінованою та дещо ефективною, хоча наразі не настільки ефективною, як інші два.

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

де функції getElem, percolateUp визначені нижче

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

Нарешті, час у середньому становив близько 15 мс для великого значення n, як показано нижче,

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]

Ви вважаєте, що відповідь складна? Що це тоді ?! І тут є інша відповідь , яка генерує багато "помилкових цілих чисел". Я запустив вашу реалізацію на прикладі введеного вами прикладу (popuSize = 1000, sampleSize = 999). Ваша версія викликає цю random.randintфункцію 3996 разів, а інша - cca. 6000 разів. Не такий великий поліпшення так?
Кирилл

@kyrill, ваша відповідь на цю відповідь
aak318

1

Для того, щоб отримати програму, яка генерує список випадкових значень без дублікатів, який є детермінованим, ефективним та побудованим за допомогою основних конструктивних програм, врахуйте функцію, extractSamplesвизначену нижче,

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

Основна ідея полягає у тому, щоб відстежувати інтервали intervalLstдля можливих значень, з яких вибирати потрібні нам елементи. Це є детермінованим у тому сенсі, що ми гарантуємо формування вибірки за фіксовану кількість кроків (виключно залежно від populationSizeтаsampleSize ).

Щоб використовувати вищевказану функцію для створення необхідного списку,

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

Ми можемо також порівняти з більш раннім рішенням (для меншої вартості кількості населення)

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

Зауважте, що я зменшив populationSizeзначення, оскільки воно створює помилку пам'яті для більш високих значень при використанні random.sampleрішення (також згадувалося в попередніх відповідях тут і тут ). За наведеними вище значеннями ми також можемо спостерігати, що extractSamplesперевершує random.sampleпідхід.

PS: Хоча основний підхід схожий на мою попередню відповідь , існують суттєві зміни в реалізації, а також підхід разом із підвищенням чіткості.


0

Дуже проста функція, яка також вирішує вашу проблему

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]

"""

0

Проблема із встановленими підходами ("якщо випадкове значення у значеннях, що повертаються, спробуйте ще раз") полягає в тому, що час їх виконання не визначений через зіткнення (що вимагає чергової ітерації "повторити спробу"), особливо коли повертається велика кількість випадкових значень з асортименту.

Альтернатива, яка не схильна до цього недетермінованого виконання, полягає в наступному:

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]

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)

1
Ласкаво просимо до Stackoverflow. Поясніть, будь ласка, свою відповідь, чому і як це вирішує проблему, щоб інші могли легко зрозуміти вашу відповідь.
жовтень

Хоча цей код може вирішити питання, включаючи пояснення, як і чому це вирішує проблему, справді допоможе покращити якість вашої публікації та, ймовірно, призведе до збільшення кількості голосів. Пам'ятайте, що ви відповідаєте на запитання читачів у майбутньому, а не лише про людину, яка зараз задає питання. Будь ласка, відредагуйте свою відповідь, щоб додати пояснення та вказати, які обмеження та припущення застосовуються. З огляду
подвійний звуковий сигнал

-1

Якщо ви хочете переконатися, що додані номери є унікальними, ви можете використовувати об'єкт Set

якщо ви використовуєте 2.7 або більше, або імпортуйте модуль наборів, якщо ні.

Як вже згадували інші, це означає, що цифри не є справді випадковими.


-1

для вибірки цілих чисел без заміни між minvalта 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]

з 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]

Чому б ви створили перестановку можливо великої кількості елементів, а потім вибрати лише перший n_samplesз них? Які ваші міркування за цим підходом? Чи можете ви пояснити, які переваги вашого підходу, порівняно з будь-якою з великої кількості відповідей (більшість із них 8 років тому)?
kyrill

насправді моя відповідь має аналогічну складність, як і інші відповіді, де голосують головні, і швидша, тому що в ній використовуються нудні. використовуються інші, голосовані методи random.shuffle, в яких використовується Mersenne Twister, але це набагато повільніше, ніж альги, пропоновані numpy (і, мабуть, jax). numpy і jax дозволяють використовувати інші алгоритми генерації випадкових чисел. jax також дозволяє компілювати і диференціювати джит, що може бути корисно для стохастичної диференціації. Крім того, щодо "можливо великого" масиву деякі голосовані відповіді роблять точно те саме random.shuffle, що я не думаю, що є грішним у відносному або навіть абсолютному сенсі
грисаїт

1
Не впевнений, що ви маєте на увазі під « random.shuffleМерсенн Твістер» - це перемішання Фішера-Йейта, про що йдеться у кількох відповідях. Він має лінійну часову складність, тому він не може бути асимптотично повільнішим, ніж алгоритми, запропоновані будь-якою іншою бібліотекою, numpy чи іншим чином. Якщо numpy швидше, то це лише тому, що воно натягнуте на C, але це не гарантує створення величезної перестановки (такої, яка може навіть не вписатись у пам'ять), а лише вибрати кілька елементів з неї. Існує не єдиний відповідь , крім вашого , який робить це.
Кирилл

Вибачте, я прочитав, що пітон випадково використовував Мерсенн Твістер в якості прнг. У вас є джерело, щоб я міг дізнатися більше про Фішера Йейта та роль у random.shuffle?
грисаїт

Тут уже є два окремих посилання на Вікіпедію на два окремих відповіді. Якщо Вікіпедія не є достатньо хорошим джерелом для вас, у кінці статті є 14 посилань. А тут ще Google. Чи допомагає це? О, і randomмодуль написаний Python, тому ви можете легко переглянути його джерело (спробувати random.__file__).
Кирилл

-3

Від CLI у win xp:

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

У Канаді у нас є 6/49 лото. Я просто загортаю вищезазначений код у lotto.bat і запускаю C:\home\lotto.batабо просто C:\home\lotto.

Тому що random.randintчасто повторює ряд, я використовую setзrange(7) , а потім скоротити його до довжини 6.

Інколи, якщо число повторюється більше, ніж у 2 рази, довжина списку буде менше 6.

EDIT: Однак random.sample(range(6,49),6)це правильний шлях.


-3
import random
result=[]
for i in range(1,50):
    rng=random.randint(1,20)
    result.append(rng)

1
Чи можете ви пояснити, як це дозволяє уникнути дублікатів? Це не очевидно з цього дампа коду.
Toby Speight

Це не так. print len(result), len(set(result)). Ви б очікували побачити, що resultунікальні елементи мали б лише один раз кожні 1.0851831788708547256608362340568947172111832359638926... × 10^20спроби.
Джедаї
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.