Bagaimana cara membuat daftar nomor acak tanpa duplikat?

110

Saya mencoba menggunakan random.randint(0, 100), tetapi beberapa angkanya sama. Apakah ada metode / modul untuk membuat daftar bilangan acak unik?

Catatan: Kode berikut ini didasarkan pada sebuah jawaban dan telah ditambahkan setelah jawaban diposting. Ini bukan bagian dari pertanyaan; itu solusinya.

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
sumber
1
Jika unik, mereka bisa benar-benar acak dalam konteks yang benar. Seperti sampel indeks acak tanpa penggantian masih bisa benar-benar acak.
gbtimmon

Jawaban:

180

Ini akan mengembalikan daftar 10 nomor yang dipilih dari kisaran 0 hingga 99, tanpa duplikat.

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

Dengan mengacu pada contoh kode spesifik Anda, Anda mungkin ingin membaca semua baris dari file satu kali dan kemudian memilih baris acak dari daftar yang disimpan di memori. Sebagai contoh:

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

Dengan cara ini, Anda hanya perlu membaca dari file tersebut satu kali, sebelum loop Anda. Jauh lebih efisien untuk melakukan ini daripada mencari kembali ke awal file dan memanggil f1.readlines()lagi untuk setiap iterasi pengulangan.

Greg Hewgill
sumber
2
Teknik ini membuang-buang memori, terutama untuk sampel yang besar. Saya memposting kode untuk lebih banyak memori dan menghitung solusi efisien di bawah ini yang menggunakan Generator Kongruensial Linear.
Thomas Lux
Saya telah ditunjukkan kepada saya bahwa metode LCG kurang "acak", jadi jika Anda ingin menghasilkan banyak urutan acak yang unik, variasinya akan lebih sedikit daripada solusi ini. Jika Anda hanya membutuhkan sedikit urutan acak, LCG adalah cara yang tepat!
Thomas Lux
Terima kasih Greg, Itu berguna
N Sivaram
15

Anda dapat menggunakan mengocok fungsi dari acak modul seperti ini:

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

Perhatikan di sini bahwa metode shuffle tidak mengembalikan daftar apa pun seperti yang diharapkan, metode ini hanya mengacak daftar yang diteruskan oleh referensi.

Ricardo Murillo
sumber
Baik untuk disebutkan di sini bahwa xrange hanya berfungsi di Python 2 dan bukan di Python 3.
Shayan Shafiq
10

Pertama-tama Anda dapat membuat daftar angka dari asampai b, di mana adan bmasing-masing merupakan angka terkecil dan terbesar dalam daftar Anda, lalu mengocoknya dengan algoritma Fisher-Yates atau menggunakan metode Python random.shuffle.

ben
sumber
1
Membuat daftar lengkap indeks adalah pemborosan memori, terutama untuk sampel yang besar. Saya memposting kode untuk lebih banyak memori dan menghitung solusi efisien di bawah ini yang menggunakan Generator Kongruensial Linear.
Thomas Lux
8

Solusi yang disajikan dalam jawaban ini berfungsi, tetapi bisa menjadi masalah dengan memori jika ukuran sampel kecil, tetapi populasinya besar (misalnya random.sample(insanelyLargeNumber, 10)).

Untuk memperbaikinya, saya akan menggunakan ini:

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
inspectorG4dget
sumber
Sekarang random.samplegunakan pendekatan ini untuk sejumlah kecil sampel dari populasi besar, jadi masalah dengan memori ini tidak benar-benar ada. Meskipun, pada saat jawaban ini ditulis, penerapannya random.shufflemungkin berbeda.
kyrill
5

Penghasil Angka Pseudo-random Kongruensial Linear

O (1) Memori

O (k) Operasi

Masalah ini dapat diatasi dengan Generator Kongruensial Linier sederhana . Ini membutuhkan overhead memori konstan (8 bilangan bulat) dan paling banyak 2 * (panjang urutan) komputasi.

Semua solusi lain menggunakan lebih banyak memori dan lebih banyak komputasi! Jika Anda hanya membutuhkan beberapa urutan acak, metode ini akan jauh lebih murah. Untuk rentang ukuran N, jika Anda ingin membuat berdasarkan urutan N- kurutan unik atau lebih, saya merekomendasikan solusi yang diterima menggunakan metode bawaan random.sample(range(N),k)karena ini telah dioptimalkan dengan python untuk kecepatan.

Kode

# 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

Pemakaian

Penggunaan fungsi "random_range" ini sama dengan generator (seperti "range"). Sebuah contoh:

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

Hasil Sampel

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
sumber
1
Ini keren sekali! Tetapi saya sangat yakin bahwa itu benar-benar menjawab pertanyaan itu; katakanlah saya ingin mengambil sampel 2 nilai dari 0 hingga 4. Tanpa menghasilkan nilai saya sendiri prime, fungsi hanya akan mengembalikan saya 4 kemungkinan jawaban, karena valuemerupakan satu-satunya hal yang dipilih secara acak dengan 4 kemungkinan nilai, ketika kita membutuhkan setidaknya (4 pilih 2) = 6, (memungkinkan untuk pemesanan non-acak). random_range(2,4)akan mengembalikan nilai {(1, 0), (3, 2), (2, 1), (0, 3)}, tapi tidak pernah pair (3,1) (atau (1,3)). Apakah Anda mengharapkan bilangan prima besar baru yang dibuat secara acak setiap panggilan fungsi?
wowserx
1
(Juga saya berasumsi bahwa Anda mengharapkan orang untuk mengacak urutan setelah fungsi Anda mengembalikannya jika mereka menginginkan pengurutan acak, karena random_range(v)mengembalikan hingga vurutan unik, bukan v!)
wowserx
Benar sekali! Sulit untuk menyeimbangkan antara menghindari overflow integer dan menghasilkan urutan acak yang cukup. Saya memperbarui fungsi untuk memasukkan lebih banyak keacakan, tetapi masih tidak seacak v !. Itu tergantung pada apakah Anda ingin menggunakan fungsi tersebut beberapa kali. Solusi ini paling baik digunakan saat Anda membuat dari berbagai nilai (saat konsumsi memori orang lain akan jauh lebih tinggi). Saya akan lebih memikirkannya, terima kasih!
Thomas Lux
4

Jika daftar nomor N dari 1 sampai N dibuat secara acak, maka ya, ada kemungkinan beberapa nomor dapat diulang.

Jika Anda menginginkan daftar angka dari 1 hingga N dalam urutan acak, isi array dengan bilangan bulat dari 1 hingga N, lalu gunakan pengacakan Fisher-Yates atau Python random.shuffle().

Mitch Wheat
sumber
3

Jika Anda perlu mengambil sampel dalam jumlah yang sangat besar, Anda tidak dapat menggunakan range

random.sample(range(10000000000000000000000000000000), 10)

karena melempar:

OverflowError: Python int too large to convert to C ssize_t

Juga, jika random.sampletidak dapat menghasilkan jumlah item yang Anda inginkan karena jangkauannya terlalu kecil

 random.sample(range(2), 1000)

itu melempar:

 ValueError: Sample larger than population

Fungsi ini menyelesaikan kedua masalah:

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

Penggunaan dengan jumlah yang sangat besar:

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

Hasil sampel:

7822019936001013053229712669368
6289033704329783896566642145909
2473484300603494430244265004275
5842266362922067540967510912174
6775107889200427514968714189847
9674137095837778645652621150351
9969632214348349234653730196586
1397846105816635294077965449171
3911263633583030536971422042360
9864578596169364050929858013943

Penggunaan dengan kisaran lebih kecil dari jumlah item yang diminta:

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

Hasil sampel:

2, 0, 1

Ini juga berfungsi dengan rentang dan langkah negatif:

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

Hasil sampel:

2, -8, 6, -2, -4, 0, 4, 10, -6, 8
-3, 1, 5, -1, 3
Pengrajin
sumber
bagaimana jika Anda menghasilkan lebih dari 8 miliar angka, cepat atau lambat terlihat akan menjadi terlalu besar
david_adler
Jawaban ini memiliki kekurangan yang parah untuk sampel besar. Probabilitas tabrakan tumbuh secara linier dengan setiap langkah. Saya memposting solusi menggunakan Linear Congruential Generator yang memiliki O (1) overhead memori dan langkah-langkah O (k) yang diperlukan untuk menghasilkan nomor k. Ini bisa diselesaikan dengan lebih efisien!
Thomas Lux
Jawaban ini pasti lebih baik jika Anda ingin menghasilkan sejumlah urutan acak dalam urutan panjang urutan! Metode LCG kurang "acak" dalam hal menghasilkan beberapa urutan unik.
Thomas Lux
"Fungsi ini menyelesaikan kedua masalah" Bagaimana cara mengatasi masalah kedua? Anda masih tidak dapat mengambil 1000 sampel dari populasi 2. Alih-alih memberikan pengecualian, Anda memberikan hasil yang salah; itu bukanlah penyelesaian dari "masalah" (yang sebenarnya bukan masalah untuk memulai karena sama sekali tidak masuk akal untuk meminta k sampel unik dari populasi n <k ).
kyrill
1

Anda dapat menggunakan Numpy perpustakaan untuk jawaban cepat seperti yang ditunjukkan di bawah ini -

Potongan kode yang diberikan mencantumkan 6 angka unik antara kisaran 0 sampai 5. Anda dapat menyesuaikan parameter untuk kenyamanan Anda.

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

Keluaran

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

Itu tidak menempatkan batasan apa pun seperti yang kita lihat di random.sample seperti yang dirujuk di sini .

Semoga ini sedikit membantu.

dataLeo
sumber
1

Jawaban yang diberikan di sini bekerja dengan sangat baik sehubungan dengan waktu serta memori tetapi sedikit lebih rumit karena menggunakan konstruksi python lanjutan seperti yield. The jawaban sederhana bekerja dengan baik dalam praktek tetapi, masalah dengan jawaban itu adalah bahwa hal itu dapat menghasilkan banyak bilangan bulat palsu sebelum benar-benar membangun set yang diperlukan. Cobalah dengan populasiSize = 1000, sampleSize = 999. Secara teori, ada kemungkinan itu tidak berakhir.

Jawaban di bawah ini membahas kedua masalah tersebut, karena bersifat deterministik dan agak efisien meskipun saat ini tidak seefisien dua lainnya.

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

dengan fungsi getElem, percolateUp seperti yang didefinisikan di bawah ini

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

Akhirnya, waktu rata-rata sekitar 15ms untuk nilai n yang besar seperti yang ditunjukkan di bawah ini,

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
sumber
Anda berpikir bahwa jawaban rumit? Lalu apa ini ?! Dan kemudian ada jawaban lain , yang menghasilkan banyak "bilangan bulat palsu". Saya menjalankan implementasi Anda dengan input contoh yang Anda berikan (populasiSize = 1000, sampleSize = 999). Versi Anda memanggil random.randintfungsi 3996 kali, sedangkan yang lainnya cca. 6000 kali. Bukan peningkatan yang besar ya?
kyrill
@kyrill, pendapat Anda tentang jawaban ini
aak318
1

Untuk mendapatkan program yang menghasilkan daftar nilai acak tanpa duplikat yang deterministik, efisien dan dibangun dengan konstruksi pemrograman dasar pertimbangkan fungsi yang extractSamplesditentukan di bawah ini,

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

Ide dasarnya adalah untuk melacak interval intervalLstuntuk kemungkinan nilai yang akan digunakan untuk memilih elemen yang kami butuhkan. Ini deterministik dalam arti bahwa kami dijamin akan menghasilkan sampel dalam sejumlah langkah tetap (hanya bergantung pada populationSizedansampleSize ).

Untuk menggunakan fungsi di atas untuk menghasilkan daftar yang kami butuhkan,

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

Kami juga dapat membandingkan dengan solusi sebelumnya (untuk nilai populasi yang lebih rendah)

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

Perhatikan bahwa saya mengurangi populationSizenilai karena menghasilkan Kesalahan Memori untuk nilai yang lebih tinggi saat menggunakan random.samplesolusi (juga disebutkan dalam jawaban sebelumnya di sini dan di sini ). Untuk nilai di atas, kami juga dapat mengamati bahwa extractSamplesmengunggulirandom.sample pendekatannya.

PS: Meskipun pendekatan intinya mirip dengan jawaban saya sebelumnya , ada modifikasi substansial dalam implementasi serta pendekatan bersama dengan peningkatan kejelasan.

aak318
sumber
0

Fungsi yang sangat sederhana yang juga menyelesaikan masalah Anda

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
sumber
0

Masalah dengan pendekatan berbasis himpunan ("jika nilai acak dalam nilai yang dikembalikan, coba lagi") adalah waktu prosesnya tidak ditentukan karena benturan (yang memerlukan iterasi "coba lagi" lainnya), terutama ketika sejumlah besar nilai acak dikembalikan dari jangkauan.

Alternatif yang tidak rentan terhadap waktu proses non-deterministik ini adalah sebagai berikut:

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]
jeruk
sumber
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)
pengguna85510
sumber
1
Selamat datang di Stackoverflow. Tolong jelaskan jawaban Anda mengapa dan bagaimana cara memecahkan masalah sehingga orang lain dapat memahami jawaban Anda dengan mudah.
octobus
Meskipun kode ini dapat menyelesaikan pertanyaan, termasuk penjelasan tentang bagaimana dan mengapa ini menyelesaikan masalah akan sangat membantu untuk meningkatkan kualitas posting Anda, dan mungkin menghasilkan lebih banyak suara. Ingatlah bahwa Anda menjawab pertanyaan untuk pembaca di masa depan, bukan hanya orang yang bertanya sekarang. Harap edit jawaban Anda untuk menambahkan penjelasan dan memberikan indikasi batasan dan asumsi apa yang berlaku. Dari Ulasan
double-beep
-1

Jika Anda ingin memastikan bahwa nomor yang ditambahkan unik, Anda dapat menggunakan objek Set

jika menggunakan 2.7 atau lebih besar, atau impor modul set jika tidak.

Seperti yang disebutkan orang lain, ini berarti jumlahnya tidak benar-benar acak.

Recaiden
sumber
-1

untuk mengambil sampel bilangan bulat tanpa penggantian antara minvaldan 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]

dengan 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
sumber
Mengapa Anda membuat permutaiton dari sejumlah besar elemen dan kemudian hanya memilih yang pertama n_samples? Apa alasan Anda di balik pendekatan ini? Dapatkah Anda menjelaskan apa keuntungan dari pendekatan Anda, dibandingkan dengan sejumlah besar jawaban yang ada (kebanyakan dari 8 tahun lalu)?
kyrill
sebenarnya jawaban saya memiliki kerumitan yang sama dengan jawaban pilihan teratas lainnya dan lebih cepat karena menggunakan numpy. lain, penggunaan metode pilihan teratas random.shuffle, yang menggunakan Mersenne Twister, qhich jauh lebih lambat daripada algos yang ditawarkan oleh numpy (dan mungkin jax). numpy dan jax memungkinkan algoritma pembuatan nomor acak lainnya. jax juga memungkinkan kompilasi jit dan diferensiasi, yang dapat berguna untuk diferensiasi stokastik. juga, mengenai array "kemungkinan besar", beberapa jawaban pilihan teratas melakukan hal yang persis sama random.shuffle, yang menurut saya tidak berdosa secara relatif atau bahkan absolut
grisaitis
1
Tidak yakin apa yang Anda maksud dengan " random.shufflemenggunakan Mersenne Twister" - ini adalah pengacakan Fisher-Yates, seperti yang disebutkan dalam beberapa jawaban. Ini memiliki kompleksitas waktu linier sehingga tidak mungkin secara asimtotik lebih lambat daripada algoritma yang ditawarkan oleh perpustakaan lain, numpy atau sebaliknya. Jika numpy lebih cepat, itu hanya karena diimplementasikan di C, tapi ini tidak menjamin menghasilkan permutasi yang besar (yang bahkan mungkin tidak muat ke dalam memori), hanya untuk memilih beberapa elemen darinya. Tidak ada jawaban tunggal selain jawaban Anda yang melakukan ini.
kyrill
Maaf, saya membaca bahwa python random menggunakan Mersenne Twister sebagai prng. Apakah Anda memiliki sumber agar saya dapat mempelajari lebih lanjut tentang Fisher Yates dan peran di random.shuffle?
grisaitis
Sudah ada dua tautan terpisah ke Wikipedia pada dua jawaban terpisah di sini. Jika Wikipedia bukan sumber yang cukup baik untuk Anda, ada 14 referensi di akhir artikel. Lalu ada Google. Apakah itu membantu? Oh, dan randommodulnya ditulis dengan Python, jadi Anda dapat dengan mudah melihat sumbernya (coba random.__file__).
kyrill
-3

Dari CLI di win xp:

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

Di Kanada kami memiliki 6/49 Lotto. Saya hanya membungkus kode di atas di lotto.bat dan menjalankan C:\home\lotto.batatau hanyaC:\home\lotto .

Karena random.randintsering mengulang angka, saya gunakan setwith range(7)dan kemudian memendekkannya menjadi 6.

Terkadang jika sebuah angka berulang lebih dari 2 kali panjang daftar yang dihasilkan akan kurang dari 6.

EDIT: Namun, random.sample(range(6,49),6)adalah cara yang benar untuk pergi.

exbctel
sumber
-3
import random
result=[]
for i in range(1,50):
    rng=random.randint(1,20)
    result.append(rng)
pengguna2904400
sumber
1
Bisakah Anda menjelaskan bagaimana ini menghindari duplikat? Tidak jelas dari dump kode ini.
Toby Speight
Tidak. print len(result), len(set(result)). Anda akan berharap untuk melihat bahwa resultakan memiliki elemen unik hanya sekali dalam setiap 1.0851831788708547256608362340568947172111832359638926... × 10^20percobaan.
Jedi