2015-12-09 90 views
0

我正在使用Laravel 5.1框架。生成並保存百萬個唯一代碼

我需要從字符'BCDFGHIJKLMNPQRSTVWXYZ'取5,例如DFGHJ創建一組唯一代碼。

所以,我的代碼是這樣的:

$maxCodes = 1200000; 
$codeSize = 5; 
$characters = 'BCDFGHJKLMNPQRSTVWXY'; 
$cLenght = strlen($characters); 
$sizeBlock = $maxCodes/($cLenght*4); // For not overflow memory when put the codes in array 

for ($i=0; $i < $cLenght; $i++) { 
    $subCharacters = str_replace($characters[$i], '', $characters); 
    $existCodes = []; 
    for ($k = 0; $k < 4; $k++) { 
     $codesToInsert = []; 
     for ($j = 0; $j < $sizeBlock;) { 
      $code = $characters[$i] . substr(str_shuffle($characters), 0, $codeSize-1); 

      if (!isset($existCodes[$code])) { 
       $existCodes[$code] = ''; 
       array_push($codesToInsert, ['code' => $code, 'used' => 0, 'rand' => rand(0,10)]); 
       $j++; 
      } 
     } 

     \App\Code::insert($codesToInsert); 
    } 
} 

我會解釋一下我的代碼。因爲我的代碼是按字母順序排列的,所以我把一個隨機數的字段rand(我創建這個字段用於下一個查詢,如Code :: where('used',0) - > where('rand',rand(0 ,9)),通過這種方式我檢索了一個隨機代碼,而不是按字母順序)

問題是當我運行函數來生成代碼,其創建只有135000不是$ maxCodes,但我不知道爲什麼? ..

有人可以幫助我嗎?

謝謝!

PS.-對不起給我English ..

+0

沒有坐下來,做了很多數學的,我懷疑你不是生成的隨機碼 - 你已經生成*按字母順序排列的每組* 5個字母組合。 – symcbean

+0

不需要,用戶可以設置maxCode。所有的可能性都是1.8Million我已經設置了1.2Million的示例代碼1.2Million – Krlinhos

+0

我懷疑爲這個長度爲5的需求生成代碼的最好方法是生成所有組合並對其進行混洗。原因是需要大量的組合並生成隨機的組合並檢查是否唯一會產生很多衝突。請參閱:[PHP算法來生成從一個集合的特定大小的所有組合](http://stackoverflow.com/questions/19067556/php-algorithm-to-generate-all-combinations-of-a-specific-size -from-A-單集)。 –

回答

0

代碼已被評論。

限制:越接近組合的限制,那麼'重複生成的計數'將變得愚蠢。我希望在我的電腦上生成所有120萬個代碼大約需要30分鐘。我預計它會花費150萬美元。很有意思。

詳細的字母 'B' 的樣品包括重複計算

$tryCount integer89166 
$existCount integer68422 

Timings: 

Script start date and time : 2015-12-09 15:45:47.172 
Script stop end date and time: 2015-12-09 15:46:40.109 
Total execution time : 52.938000000000002 

樣品:

'BXCLF' => integer 6 
'BYRXS' => integer 6 
'BPGGG' => integer 6 
'BRQJJ' => integer 6 
'BKJKQ' => integer 6 
'BNQVG' => integer 6 
'BLQSX' => integer 6 
'BCGDH' => integer 5 
'BBLFG' => integer 5 
'BFBJQ' => integer 5 
'BRVRJ' => integer 5 
'BJXTX' => integer 5 

硬件:電腦 - 雙倉鼠供電。

RandomData類的代碼:Random data for use in PHP

代碼:

<?php 

include __DIR__ . '/__bootstrap__.php'; 

use app\system\encryption\RandomData; 
use app\system\ElapsedTiming; 

$maxCodes = 50000; 
$codeSize = 5; 
$characters = 'BCDFGHJKLMNPQRSTVWXY'; 
$cLength = strlen($characters) - 1; 

$codesPerLetter = (int) $maxCodes/$cLength; // how many to generate for this initial letter 

$timer = new ElapsedTiming(); 
$timer->start(); 

/** 
* @var RandomData 
*/ 
$randSrc = RandomData::instance(); // source of random numbers 

for ($i=0; $i < $cLength; $i++) { // use each char as an initial character 

    $existCodes = array(); // current batch of codes in here 
    $existCount = 0; 

    $newCode = $characters[$i] . '0000'; // each `batch` starts with a different letter 
             // then four random letters from the string... 

    $tryCount = 0; // count the number of attemps to generate the required count 
    while ($existCount < $codesPerLetter) { 

     // generate a random 4 character string using all the characters 
     for ($k = 1; $k < 5 ; $k++) { // first lether is fixed then fill in the rest 
      // generate code... 
      $char = $characters[$randSrc->int32(0, $cLength)]; 
      $newCode[$k] = $char; 
     } 

     $tryCount++; 

     // test if exists 
     if (isset($existCodes[$newCode])) { // store as keys not values 
      $existCodes[$newCode]++;   // count duplicate generation 
     } 
     else { 
      $existCodes[$newCode] = 1;  // a new one 
      $existCount++;     // closer to the target 
     } 
    } 

    /** 
    * Write this batch of codes to the array to the database... 
    */ 
} 

/* debug information */ 
$timer->stop(); 
arsort($existCodes); 

$timer->printFullStats(); 

\Kint::dump($tryCount, $existCount, array_slice($existCodes, 0, 100)); 
+0

對不起Ryan,但我不明白你:(你說我的代碼需要大約30分鐘嗎?但是你的建議少花錢嗎?那麼只有我必須改變你提到的代碼,謝謝! – Krlinhos

+0

@Krlinhos,對不起,我只提供了我提供的代碼的時間,與你的代碼相比,主要區別在於它爲每個新代碼選擇了18個字符中的4個隨機字符,然後檢查是否它是一個新的代碼,計時是針對我的PC的,大約需要一分鐘才能生成60000個(六萬個)唯一代碼,'trycount'和'existCount'之間的區別就是生成的重複次數。 –