Yinelenmeyen rastgele sayılardan oluşan bir listeyi nasıl oluştururum?


110

Kullanmayı denedim random.randint(0, 100)ama bazı rakamlar aynıydı. Benzersiz rastgele sayılar listesi oluşturmak için bir yöntem / modül var mı?

Not: Aşağıdaki kod bir yanıta dayanmaktadır ve yanıt gönderildikten sonra eklenmiştir. Sorunun bir parçası değil; çözüm bu.

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
Benzersizlerse, doğru bağlamda gerçekten rastgele olabilirler. Rastgele bir dizin örneği gibi, değiştirilmeden tamamen rastgele olabilir.
gbtimmon

Yanıtlar:


180

Bu, kopya olmadan, 0 - 99 aralığından seçilen 10 numaradan oluşan bir liste döndürür.

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

Özel kod örneğinize göre, muhtemelen dosyadaki tüm satırları bir kez okumak ve ardından bellekteki kayıtlı listeden rastgele satırlar seçmek istersiniz . Örneğin:

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

Bu şekilde, döngünüzden önce dosyadan yalnızca bir kez okumanız gerekir. Bunu yapmak, dosyanın başlangıcına geri dönüp f1.readlines()her döngü yinelemesi için yeniden aramaktan çok daha etkilidir .


2
Bu teknik, özellikle büyük numuneler için hafızayı boşa harcar. Doğrusal Kongruential Generator kullanan çok daha fazla bellek ve hesaplama açısından verimli bir çözüm için kod gönderdim.
Thomas Lux

Bana LCG yönteminin daha az "rasgele" olduğu belirtildi, bu nedenle çok sayıda benzersiz rasgele dizi oluşturmak istiyorsanız, çeşitlilik bu çözümden daha az olacaktır. Yalnızca birkaç rastgele diziye ihtiyacınız varsa, LCG tam size göre!
Thomas Lux

Teşekkürler Greg,
Faydalıydı

15

Rastgele modülden shuffle işlevini şu şekilde kullanabilirsiniz :

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

Burada shuffle yönteminin beklendiği gibi herhangi bir liste döndürmediğini, yalnızca referansla iletilen listeyi karıştırdığını unutmayın.


Burada xrange'in yalnızca Python 2'de çalıştığını ve Python 3'te çalışmadığını belirtmek güzel.
Shayan Shafiq

10

Önce gelen numaralarının bir listesini oluşturabilir aiçin bnerede, ave bsırasıyla listenizde en küçük ve en büyük sayılardır, sonra onu karıştırmak Fisher-Yates algoritması veya Python'un kullanarak random.shuffleyöntemi.


1
Tam bir dizin listesi oluşturmak, özellikle büyük örnekler için bellek israfıdır. Doğrusal Kongruential Generator kullanan çok daha fazla bellek ve hesaplama açısından verimli bir çözüm için kod gönderdim.
Thomas Lux

8

Bu cevapta sunulan çözüm işe yarıyor, ancak örneklem boyutu küçükse, ancak popülasyon çok büyükse (örneğin random.sample(insanelyLargeNumber, 10)) bellekle ilgili sorunlu hale gelebilir .

Bunu düzeltmek için şununla giderdim:

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

Şimdi random.samplebu yaklaşımı büyük bir popülasyondan az sayıda örnek için kullanıyor, bu nedenle bellekle ilgili bu sorun artık gerçekten mevcut değil. Her ne kadar bu cevap yazıldığı sırada, uygulaması random.shufflefarklı olabilirdi.
kyrill

5

Doğrusal Eşleşik Sözde Rastgele Sayı Üreticisi

O (1) Hafıza

O (k) İşlemler

Bu problem basit bir Doğrusal Eşgüdümlü Üretici ile çözülebilir . Bu, sabit bellek ek yükü (8 tam sayı) ve en fazla 2 * (sıra uzunluğu) hesaplamaları gerektirir.

Diğer tüm çözümler daha fazla bellek ve daha fazla bilgi işlem kullanır! Yalnızca birkaç rastgele diziye ihtiyacınız varsa, bu yöntem önemli ölçüde daha ucuz olacaktır. Boyutta aralıkları için Nsize sırasına oluşturmak istiyorsanız, Nbenzersiz kdaha dizileridir ya, ben yerleşik yöntemleri kullanarak kabul çözümü tavsiye random.sample(range(N),k)bu şekilde optimize edilmiştir hız için python.

Kod

# 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

Kullanım

Bu "rasgele_aralık" işlevinin kullanımı, herhangi bir oluşturucu ile aynıdır ("aralık" gibi). Bir örnek:

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

Örnek Sonuçlar

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
Bu çok havalı! Ama soruyu gerçekten cevapladığından eminim; Diyelim ki 0'dan 4'e kadar 2 değeri örneklemek istiyorum. Kendi yanıtımı oluşturmadan prime, işlev bana yalnızca 4 olası yanıt döndürecektir, çünkü valueen az ihtiyacımız olduğunda 4 olası değerle rastgele seçilen tek şeydir (4 2'yi seçin) = 6, (rastgele olmayan sıralamaya izin verir). random_range(2,4){(1, 0), (3, 2), (2, 1), (0, 3)} değerlerini döndürür, ancak hiçbir zaman (3,1) (veya (1,3)) çifti döndürmez. Her işlev çağrısı için yeni rastgele oluşturulmuş büyük asal sayılar mı bekliyorsunuz?
wowserx

1
(Ayrıca, rastgele sıralama isterlerse, işleviniz döndükten sonra diziyi karıştırmalarını beklediğinizi varsayıyorum, çünkü bunun yerine benzersiz dizilere random_range(v)dönüyor )vv!
wowserx

Tamamıyla doğru! Tam sayı taşmasını önlemek ile yeterli sayıda rastgele diziler oluşturmak arasında denge kurmak zordur. İşlevi biraz daha fazla rastgelelik içerecek şekilde güncelledim, ancak yine de v! Kadar rastgele değil. İşlevi birden çok kez kullanmak isteyip istemediğinize bağlıdır. Bu çözüm, en iyi, geniş bir değer aralığından (başkalarının bellek tüketiminin çok daha yüksek olacağı durumlarda) üretilirken kullanılır. Bunun üzerinde daha fazla düşüneceğim, teşekkürler!
Thomas Lux

4

1'den N'ye kadar N sayı listesi rasgele oluşturulursa, evet, bazı sayıların tekrarlanma olasılığı vardır.

Rastgele bir sırada 1'den N'ye kadar bir sayı listesi istiyorsanız, 1'den N'ye kadar tam sayılarla bir dizi doldurun ve ardından bir Fisher-Yates karışık veya Python kullanın random.shuffle().


3

Çok büyük sayıları örneklemeniz gerekiyorsa, kullanamazsınız range

random.sample(range(10000000000000000000000000000000), 10)

çünkü fırlatır:

OverflowError: Python int too large to convert to C ssize_t

Ayrıca, random.samplearalığın çok küçük olması nedeniyle istediğiniz sayıda ürün üretemiyorsanız

 random.sample(range(2), 1000)

atar:

 ValueError: Sample larger than population

Bu işlev her iki sorunu da çözer:

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

Çok büyük sayılarla kullanım:

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

Örnek sonuç:

7822019936001013053229712669368
6289033704329783896566642145909
2473484300603494430244265004275
5842266362922067540967510912174
6775107889200427514968714189847
9674137095837778645652621150351
9969632214348349234653730196586
1397846105816635294077965449171
3911263633583030536971422042360
9864578596169364050929858013943

Aralığın istenen öğe sayısından daha küçük olduğu kullanım:

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

Örnek sonuç:

2, 0, 1

Negatif aralıklarla ve adımlarla da çalışır:

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

Örnek sonuçlar:

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

ya 8 milyardan fazla sayı
üretirseniz

Bu cevabın büyük örnekler için ciddi bir kusuru vardır. Çarpışma olasılığı her adımda doğrusal olarak artar. O (1) bellek ek yükü ve k sayıları oluşturmak için gerekli O (k) adımları olan bir Doğrusal Eşgüdüm Üreteci kullanarak bir çözüm gönderdim. Bu çok daha verimli bir şekilde çözülebilir!
Thomas Lux

Dizinin uzunluğunun sırasına göre bir dizi rastgele dizi oluşturmak istiyorsanız, bu cevap kesinlikle daha iyidir! LCG yöntemi, birden çok benzersiz sekans oluşturma söz konusu olduğunda daha az "rastgele" dir.
Thomas Lux

"Bu işlev her iki sorunu da çözer" İkinci sorunu nasıl çözer ? Hala 2 kişilik bir popülasyondan 1000 örnek alamazsınız. Bir istisna atmak yerine yanlış bir sonuç üretirsiniz; Bu, "sorunun" çözümü pek de zor değildir ( n <k popülasyonundan k benzersiz örnek istemek hiç de mantıklı olmadığından, başlamak için gerçekten bir sorun değildir ).
kyrill

1

Aşağıda gösterildiği gibi hızlı cevap için Numpy kitaplığını kullanabilirsiniz -

Verilen kod parçacığı , 0 ila 5 arasında 6 benzersiz sayıyı listeler . Konforunuz için parametreleri ayarlayabilirsiniz.

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

Çıktı

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

Anılan biz random.sample gördüğünüz gibi herhangi kısıtlamalar koymak değil burada .

Umarım bu biraz yardımcı olur.


1

Burada verilen cevap , zaman ve bellek açısından çok iyi çalışıyor, ancak verim gibi gelişmiş python yapılarını kullandığından biraz daha karmaşık. Daha basit cevap pratikte işe yarar, ancak bu cevapla ilgili sorun, gerekli seti fiilen oluşturmadan önce birçok sahte tamsayı üretebilmesidir. PopülasyonSize = 1000, sampleSize = 999 ile deneyin. Teoride, sonlanmama şansı vardır.

Aşağıdaki cevap, deterministik ve bir şekilde verimli olduğu için her iki sorunu da ele alıyor, ancak şu anda diğer ikisi kadar verimli değil.

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 işlevleri aşağıda tanımlandığı gibidir

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

Son olarak, aşağıda gösterildiği gibi büyük bir n değeri için ortalama zamanlama yaklaşık 15 ms idi,

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]

Sence bu cevabı karmaşıktır? Bu ne o zaman ?! Ve sonra birçok "sahte tam sayı" üreten başka bir cevap var . Uygulamanızı verdiğiniz örnek girdi ile çalıştırdım (popülasyonSize = 1000, sampleSize = 999). Sizin sürümünüz random.randintişlevi 3996 kez çağırırken, diğeri cca. 6000 defa. O kadar büyük bir gelişme değil ha?
kyrill


1

Belirleyici, verimli ve temel programlama yapılarıyla oluşturulmuş, yinelemeleri olmayan rastgele değerlerin bir listesini oluşturan bir program elde etmek için extractSamplesaşağıda tanımlanan işlevi göz önünde bulundurun ,

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

Temel fikir, intervalLstgerekli öğelerimizi seçebileceğimiz olası değerler için aralıkları takip etmektir. Bu, sabit sayıda adımda bir örnek oluşturmamızın garanti edilmesi anlamında belirleyicidir (yalnızca populationSizevesampleSize ).

Gerekli listemizi oluşturmak için yukarıdaki işlevi kullanmak için,

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

Daha önceki bir çözümle de karşılaştırabiliriz (daha düşük bir popülasyon boyutu için)

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

Çözümü populationSizekullanırken daha yüksek değerler için Bellek Hatası ürettiğinden değeri düşürdüğüme dikkat edin random.sample(ayrıca burada ve burada önceki yanıtlarda da bahsedilmiştir ). Yukarıdaki değerler için, biz de o gözlemleyebilirsiniz extractSamplesiyi performans random.sampleyaklaşımı.

Not: Temel yaklaşım önceki cevabıma benzer olsa da , uygulamada ve yaklaşımda netlikte iyileşme ile birlikte önemli değişiklikler var.


0

Sorununuzu da çözen çok basit bir işlev

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

Küme tabanlı yaklaşımlarla ilgili sorun ("dönüş değerlerinde rastgele değer varsa, tekrar deneyin"), özellikle büyük miktarda rastgele değer döndürüldüğünde, çarpışmalar nedeniyle (başka bir "tekrar deneyin" yinelemesi gerektiren) çalışma sürelerinin belirlenmemiş olmasıdır. aralıktan.

Bu deterministik olmayan çalışma zamanına yatkın olmayan bir alternatif şudur:

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'a hoş geldiniz. Lütfen cevabınızı başkalarının cevabınızı kolayca anlayabilmesi için sorunun neden ve nasıl çözdüğünü açıklayın.
octobus

Bu kod soruyu çözebilirken, sorunun nasıl ve neden çözüldüğüne dair bir açıklama da dahil olmak üzere , gönderinizin kalitesini artırmaya gerçekten yardımcı olur ve muhtemelen daha fazla oy almanıza neden olur. Sadece şu anda soran kişi için değil, gelecekte okuyucular için soruyu yanıtladığınızı unutmayın. Açıklamalar eklemek ve hangi sınırlamaların ve varsayımların geçerli olduğuna dair bir gösterge vermek için lütfen yanıtınızı düzenleyin . Yorumdan
double-beep

-1

Eklenen numaraların benzersiz olmasını sağlamak istiyorsanız, bir Set nesnesi kullanabilirsiniz.

2.7 veya üstü kullanılıyorsa, yoksa setler modülünü içe aktarın.

Diğerlerinin de belirttiği gibi, bu, sayıların gerçekten rastgele olmadığı anlamına gelir.


-1

arasındaki yerine koymadan örnek tamsayılar için minvalve 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 ile:

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]

Neden muhtemelen çok sayıda elemandan oluşan bir permütasyon üretip sonra sadece ilkini seçiyorsunuz n_samples? Bu yaklaşımın arkasındaki gerekçeniz nedir? Çok sayıda mevcut yanıtlardan herhangi birine kıyasla (çoğu 8 yıl öncesinden) yaklaşımınızın avantajlarını açıklayabilir misiniz?
kyrill

aslında cevabım diğer en çok oylanan cevaplarla benzer karmaşıklığa sahiptir ve daha hızlıdır çünkü numpy kullanır. random.shuffleMersenne Twister kullanan diğer, en çok oy alan yöntemler kullanılır ; bu, numpy (ve muhtemelen jax) tarafından sunulan algos'tan çok daha yavaştır. numpy ve jax, diğer rastgele sayı oluşturma algoritmalarına izin verir. jax ayrıca stokastik farklılaştırma için yararlı olabilecek jit-derlemeye ve farklılaştırmaya da izin verir. ayrıca, "muhtemelen büyük" bir dizi ile ilgili olarak, en çok oy alan cevaplardan bazıları aynı şeyi yapıyor random.shuffle, ki bu görece veya mutlak anlamda günahkar olduğunu düşünmüyorum
grisaitis

1
" random.shuffleMersenne Twister kullanır " ile ne demek istediğinizden emin değilim - bu, birkaç cevapta belirtildiği gibi Fisher-Yates karıştırmasıdır. Doğrusal zaman karmaşıklığına sahiptir, bu nedenle başka herhangi bir kitaplık tarafından sunulan algoritmalardan asimptotik olarak daha yavaş olamaz. Eğer uyuşuk daha hızlıysa, bunun nedeni sadece C'ye yerleştirilmiş olmasıdır, ancak bu büyük bir permütasyon (hafızaya bile sığmayabilir) oluşturmayı garanti etmez, sadece ondan birkaç öğe seçmeyi garanti eder. Bir yoktur tek bunu yapar senin yanında cevap.
kyrill

Özür dilerim, python random'un Mersenne Twister'ı ilk olarak kullandığını okudum. Fisher Yates ve random.shuffle'daki rol hakkında daha fazla bilgi edinebilmek için bir kaynağınız var mı?
grisaitis

Zaten burada iki ayrı cevapta Wikipedia'ya iki ayrı bağlantı var. Wikipedia sizin için yeterince iyi bir kaynak değilse, makalenin sonunda 14 referans var. Bir de Google var. Bu yardımcı olur mu? Oh, ve randommodül Python'da yazılmıştır, böylece kaynağını kolayca görüntüleyebilirsiniz (deneyin random.__file__).
kyrill

-3

Xp kazanmak için CLI'den:

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

Kanada'da 6/49 Lotto'ya sahibiz. Yukarıdaki kodu sadece lotto.bat içine sarıyorum ve koşuyorum C:\home\lotto.batya da sadeceC:\home\lotto .

Çünkü random.randintçoğu zaman bir numara tekrarlar, kullandığım setile range(7)ve daha sonra 6 uzunluğunda kadar kısaltın.

Bazen bir sayı 2 kattan fazla tekrar ederse, ortaya çıkan liste uzunluğu 6'dan az olacaktır.

DÜZENLEME: Ancak, random.sample(range(6,49),6)gitmenin doğru yolu.


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

1
Bunun kopyaları nasıl önlediğini açıklayabilir misiniz? Bu kod dökümünden açık değil.
Toby Speight

Öyle değil. print len(result), len(set(result)). resultHer 1.0851831788708547256608362340568947172111832359638926... × 10^20denemede yalnızca bir kez benzersiz öğelere sahip olacağını görmeyi beklersiniz .
Jedi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.