rasgele ve benzersiz alt-kümeleri üretimi

4 Cevap php

Biz 1-25 numaraları var ve biz 15 sayı kümesi seçmek var diyelim.

Birazdan 3268760 yaşıyorum mümkünse setleri vardır.

Bu 3268760 seçenekler, size 100.000 söylemek oluşturmak zorunda

Ne iyi benzersiz 100.000 oluşturmak için yol ve alt kümeleri rastgele olurdu?

Bunu yapmak için bir yol, bir algoritma var mı?

Eğer değilse, ne çiftleri tespit etmek için en iyi seçenek olacaktır?

I'm planning to do this on PHP but a general solution would be enough, and any reference not to much 'academic' (more practical) would help me a lot.

4 Cevap

İşte bunu düşünüyordum nasıl MJV cevabı, üzerinde PHP tabanlı bir çözüm. Tam bir 100k kümeleri için çalıştırırsanız, size gerçekten çarpışmalar bir sürü görüyorum. Ancak, zor bunları önlemek için bir sistem hazırlamak için basılı ediyorum. Bunun yerine, sadece oldukça hızlı bir şekilde onları kontrol edin.

Ben bu laptop, ben 5 saniye içinde 10k set yapabilirim ... daha iyi çözümler hakkında düşüneceğim, 20k 20 saniyenin altında ayarlar. 100k birkaç dakika sürer.

Setleri (32-bit) ints olarak temsil edilmektedir.

<?PHP
    /* (c) 2009 tim - anyone who finds a use for this is very welcome to use it with no restrictions unless they're making a weapon */

    //how many sets shall we generate?
    $gNumSets = 1000;

    //keep track of collisions, just for fun.
    $gCollisions = 0;

    $starttime = time();

    /**
     * Generate and return an integer with exactly 15 of the lower 25 bits set (1) and the other 10 unset (0)
     */ 
    function genSetHash(){
      $hash = pow(2,25)-1;

      $used = array();

      for($i=0;$i<10;){

        //pick a bit to turn off
        $bit = rand(0,24);

        if (! in_array($bit,$used)){
          $hash =  ( $hash & ~pow(2,$bit) );
          $i++;  
          $used[] = $bit;  
        }
      }
      return  $hash;
    }

    //we store our solution hashes in here.  
    $solutions = array();

    //generate a bunch of solutions.
    for($i=0;$i<$gNumSets;){
      $hash = genSetHash(); 

      //ensure no collisions
      if (! in_array($hash,$solutions)){
        $solutions[] = $hash;
        //brag a little.
        echo("Generated $i random sets in " . (time()-$starttime) . " seconds.\n");
        $i++;
      }else { 
        //there was a collision. There will generally be more the longer the process runs.
        echo "thud.\n"; 
        $gCollisions++;
      }
    }

    // okay, we're done with the hard work.  $solutions contains a bunch of
    // unique, random, ints in the right range.  Everything from here on out
    // is just output.

    //takes an integer with 25 significant digits, and returns an array of 15 numbers between 1 and 25
    function hash2set($hash){
      $set = array();
      for($i=0;$i<24;$i++){  
        if ($hash & pow(2,$i)){
          $set[] = $i+1;
        }
      }
      return $set;
    }

    //pretty-print our sets.
    function formatSet($set){
      return "[ " . implode(',',$set) . ']';
    }

    //if we wanted to print them, 
    foreach($solutions as $hash){
      echo formatSet(hash2set($hash)) . "\n";
    }

    echo("Generated $gNumSets unique random sets in " . (time()-$starttime) . " seconds.\n");

    echo "\n\nDone.  $gCollisions collisions.\n";

Ben tüm doğru olduğunu düşünüyorum, ama geç oldu, ve ben bira birkaç çok güzel şişe zevk oldum.

Çoğaltmaları için değil garanti rastgele alt kümeleri, bir örnek oluşturmak için bir yol yoktur, O (1) depolama kullanır ve herhangi bir zamanda yeniden oluşturulabilir. İlk olarak, generate a combination given its lexical index bir fonksiyon yazmak. İkincisi, bir rasgele bu kombinasyonları aracılığıyla adıma bir pseudorandom permutation of the first Combin(n, m) integers kullanın. Bunun için permütasyon içine numaraları 0 ... 100000 doyurmaya kombinasyon jeneratör giriş olarak permütasyon çıkışını kullanmak ve elde edilen kombinasyon işlem.

Onlar gerçekten rastgele olmak zorunda mı? Veya rasgele?

Seçim: tüm 25 ile bir dizi oluşturmak - "shuffle" Fisher-Yates / Knuth shuffle kullanarak ilk 15 element ve daha önce ilk 15 yapðlarðnðn permütasyonunu gördüm eğer kontrol edin. Eğer öyleyse, vurdumduymazlık, ve yeniden deneme.

Çoğaltır: Sen var ya da yok 25 değerlere sahip - bu trivially ikinci ise, vb, 2 ^ 1 ekleyin, 1 eleman varsa, 2 ^ 0 ekleyebilir (bir tamsayı değeri sağlaması olabilir - bu olabilir doğrudan 25 bit sayısı) olarak temsil, böylece zaten gördüm eğer kolayca kontrol edebilirsiniz.

Sen çarpışmalar adil biraz alırsınız, ama o bir performans kritik pasajı değilse, bu yapılabilir olabilir.

Ortamınızın rasgele sayı üreteci (RNG) size eşit olarak belirli bir aralıkta dağıtılan rasgele numaralar tedarik edecek. Dağılım Bu tür genellikle alt kümesidir piyango çizimleri taklit eğer gerekli ne demek olduğunu, ancak sizin modelleme bir orta okulun gerekçesiyle bulunan kişilerin yaş demek durumda bu gerçeği söz önemlidir ...

Bu RNG göz önüne alındığında 1 ile 25 arasında, 10 (veya 15, aşağıda okuyabilirsiniz) sayılar. Bu gerektirebilir "çizmek" olduğunu çarpın (ve yuvarlak) rastgele jeneratör tarafından üretilen sayı ve 25 üzerinde olan sayıları görmezden ( yani RNG ile ilgili kesin API bağlı olarak) tekrar çizmek, ama yine belirli bir aralıkta bir çizim almak saçmadır. Bir numara tekrar geldiğinde de yeniden beraberlik gerekir.

Ben bu 15 bir dizi üretmek için 1-25 tam diziden çıkarılabilir gibi, sadece 10 sayı almanızı öneririm. Koymak için 15 çizim başka bir deyişle çıkarmak için aynı çizim 10 In ...

Sonra setleri teklik iddia gerekir. Aksine bütün set depolamak yerine, benzersiz, her set tanımlamak için bir karma kullanabilirsiniz. Bu daha az olduğu 25 bit almalı, yani bir 32 bit tamsayı saklanabilir. Daha sonra bu değerler için 100.000 için verimli depolama olması gerekir; Bir veritabanında bu saklamak istediğiniz sürece.

Tüm olası setleri dışında alınan 100.000 setleri tekliği bu soru üzerine, bir çarpışma ihtimali oldukça düşük görünmektedir. Edit: Hata ... ben iyimser oldu ... Bu olasılık 50.000 inci çizdikten sonra bir çarpışma başlayan yaklaşık% 1.5 şans ile, çok düşük değil, onları dışlamak için bir sistem gerektirecek kadar epeyce çarpışmalar, orada olacak ...