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);
Jawaban:
Ini akan mengembalikan daftar 10 nomor yang dipilih dari kisaran 0 hingga 99, tanpa duplikat.
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:
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.sumber
Anda dapat menggunakan mengocok fungsi dari acak modul seperti ini:
Perhatikan di sini bahwa metode shuffle tidak mengembalikan daftar apa pun seperti yang diharapkan, metode ini hanya mengacak daftar yang diteruskan oleh referensi.
sumber
Pertama-tama Anda dapat membuat daftar angka dari
a
sampaib
, di manaa
danb
masing-masing merupakan angka terkecil dan terbesar dalam daftar Anda, lalu mengocoknya dengan algoritma Fisher-Yates atau menggunakan metode Pythonrandom.shuffle
.sumber
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:
sumber
random.sample
gunakan pendekatan ini untuk sejumlah kecil sampel dari populasi besar, jadi masalah dengan memori ini tidak benar-benar ada. Meskipun, pada saat jawaban ini ditulis, penerapannyarandom.shuffle
mungkin berbeda.Penghasil Angka Pseudo-random Kongruensial Linear
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 urutanN
-k
urutan unik atau lebih, saya merekomendasikan solusi yang diterima menggunakan metode bawaanrandom.sample(range(N),k)
karena ini telah dioptimalkan dengan python untuk kecepatan.Kode
Pemakaian
Penggunaan fungsi "random_range" ini sama dengan generator (seperti "range"). Sebuah contoh:
Hasil Sampel
sumber
prime
, fungsi hanya akan mengembalikan saya 4 kemungkinan jawaban, karenavalue
merupakan 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?random_range(v)
mengembalikan hinggav
urutan unik, bukanv!
)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()
.sumber
Jika Anda perlu mengambil sampel dalam jumlah yang sangat besar, Anda tidak dapat menggunakan
range
karena melempar:
Juga, jika
random.sample
tidak dapat menghasilkan jumlah item yang Anda inginkan karena jangkauannya terlalu kecilitu melempar:
Fungsi ini menyelesaikan kedua masalah:
Penggunaan dengan jumlah yang sangat besar:
Hasil sampel:
Penggunaan dengan kisaran lebih kecil dari jumlah item yang diminta:
Hasil sampel:
Ini juga berfungsi dengan rentang dan langkah negatif:
Hasil sampel:
sumber
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.
Keluaran
Itu tidak menempatkan batasan apa pun seperti yang kita lihat di random.sample seperti yang dirujuk di sini .
Semoga ini sedikit membantu.
sumber
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.
dengan fungsi getElem, percolateUp seperti yang didefinisikan di bawah ini
Akhirnya, waktu rata-rata sekitar 15ms untuk nilai n yang besar seperti yang ditunjukkan di bawah ini,
sumber
random.randint
fungsi 3996 kali, sedangkan yang lainnya cca. 6000 kali. Bukan peningkatan yang besar ya?Untuk mendapatkan program yang menghasilkan daftar nilai acak tanpa duplikat yang deterministik, efisien dan dibangun dengan konstruksi pemrograman dasar pertimbangkan fungsi yang
extractSamples
ditentukan di bawah ini,Ide dasarnya adalah untuk melacak interval
intervalLst
untuk 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 padapopulationSize
dansampleSize
).Untuk menggunakan fungsi di atas untuk menghasilkan daftar yang kami butuhkan,
Kami juga dapat membandingkan dengan solusi sebelumnya (untuk nilai populasi yang lebih rendah)
Perhatikan bahwa saya mengurangi
populationSize
nilai karena menghasilkan Kesalahan Memori untuk nilai yang lebih tinggi saat menggunakanrandom.sample
solusi (juga disebutkan dalam jawaban sebelumnya di sini dan di sini ). Untuk nilai di atas, kami juga dapat mengamati bahwaextractSamples
mengunggulirandom.sample
pendekatannya.PS: Meskipun pendekatan intinya mirip dengan jawaban saya sebelumnya , ada modifikasi substansial dalam implementasi serta pendekatan bersama dengan peningkatan kejelasan.
sumber
Fungsi yang sangat sederhana yang juga menyelesaikan masalah Anda
sumber
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:
sumber
sumber
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.
sumber
untuk mengambil sampel bilangan bulat tanpa penggantian antara
minval
danmaxval
:dengan jax:
sumber
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)?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 samarandom.shuffle
, yang menurut saya tidak berdosa secara relatif atau bahkan absolutrandom.shuffle
menggunakan 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.random
modulnya ditulis dengan Python, jadi Anda dapat dengan mudah melihat sumbernya (cobarandom.__file__
).Dari CLI di win xp:
Di Kanada kami memiliki 6/49 Lotto. Saya hanya membungkus kode di atas di lotto.bat dan menjalankan
C:\home\lotto.bat
atau hanyaC:\home\lotto
.Karena
random.randint
sering mengulang angka, saya gunakanset
withrange(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.sumber
sumber
print len(result), len(set(result))
. Anda akan berharap untuk melihat bahwaresult
akan memiliki elemen unik hanya sekali dalam setiap1.0851831788708547256608362340568947172111832359638926... × 10^20
percobaan.