How to improve the process of generating unrepeated random numbers?

Asked

Viewed 2,082 times

4

I have a randomized number creation algorithm for lotteries that have the following characteristics:

1° The number to be generated must be reported.

2° Numbers cannot be repeated.

3° Numbers need to be in ascending order.

Since I’m a beginner in PHP, I tried to make "the algorithm work". For this, I created a class with a function geraNumeros() recursively in order to make all these items and return me an array where I sort using the asort() and then turn into string with implode(). Is there any way to optimize it ?

<?php

class loterias{

   public function geraNumero($aQuantidade, $aMinimo, $aMaximo) {

      $contador = 0;
      $result = array();
      while ($aQuantidade):
         $result[$aQuantidade] = str_pad(rand($aMinimo, $aMaximo), 2, '0', STR_PAD_LEFT);
         $aQuantidade--;
         $contador++;
      endwhile;
      while ($contador !== count(array_unique($result))):
         $result = $this->geraNumero($contador, $aMinimo, $aMaximo);
      endwhile;
      return $result;
   }

}

// Parametros //
$quantidade = 6;
$minimo = 1;
$maximo = 60;

$mega = new loterias();
$result = $mega->geraNumero($quantidade, $minimo, $maximo);
asort($result);
var_dump($result);
  • 1

    Do you have any specific complaints? It is certainly possible to optimize, but need?

  • to start, I wanted to leave all the treatment inside the generating function, using the asort($result) before the Return and in the Return use the Return implode(' - ',$result); to get out a string, It happens that when the one of the values of this array repeats and enters the second while and generates new non-repeating numbers, when it goes pro Return it goes back in the asort and picks up the repeated numbers. I didn’t understand why then I had to do the treatment outside the function, and I also find it slow...

  • Another thing: it needs to be recursive?

  • I couldn’t do without being recursive...

  • 2

    Take a look at these questions, see if any serve: http://answall.com/search?q=fisher+yates - Fisher-Yates is suitable for lottery, you scramble the number set and take as many numbers as necessary.

2 answers

6


With some functions for arrays I got the same result, follows explanation of what makes each function:

range() - Create an array from a minimum and maximum.

array_rand() - Randomly returns a key from an array. With the second parameter you can specify the number of elements you want to return.

array_flip() - Invert the value with the key of an array. I did this because in PHP the keys start with zero, and I think lotteries do not start with zero.

array_map() - For each element of an array, it executes a certain function, in case it would be the str_pad with the necessary parameters.

<?php

function geraNumeros($quantidade, $minimo, $maximo)
{
    $listaDeNumeros = range($minimo, $maximo);
    $numeros = array_rand(array_flip($listaDeNumeros), $quantidade);

    $numeros = array_map(function($value){
        return str_pad($value, 2, '0', STR_PAD_LEFT);   
    }, $numeros);

    return implode($numeros, ',');
}

echo geraNumeros(6, 1, 60) . PHP_EOL;
echo geraNumeros(6, 1, 60) . PHP_EOL;
echo geraNumeros(6, 1, 60) . PHP_EOL;
echo geraNumeros(6, 1, 60) . PHP_EOL;

Example in Ideone.

  • I tested your solution and this congratulations, same features more performance. would it be possible to put str_pad to add '0' in numbers that only have 1 character? getting 01 - 05 ...

  • @Gabrielrodrigues complemented with an array_map

  • funny, I tested the solution of array_map in php 5.2 and it did not work, now I tested in the last version 5.6.4 and it worked, I saw the documentation of php array_map and it is available from 4, there is some module/restriction that has to enable to work ?

  • 1

    @Gabrielrodrigues did not work because of the closures, or Anonimas functions, the part of function(). If you really need the code running in PHP 5.2, replace the array_map with a loop.

  • http://php.net/manual/en/functions.anonymous.php Note: Anonimas functions are available since PHP 5.3.0. I get it. I will loop then.

4

I leave a solution which, in my opinion, has a simple code:

<?php

class loterias{

   public function geraNumero($aQuantidade, $aMinimo, $aMaximo) {
       if( $aQuantidade > ($aMaximo - $aMinimo) ) {
           return false;
       }

       $numeros = range($aMinimo, $aMaximo);
       shuffle($numeros);
       array_splice($numeros, 0, $aQuantidade);
       sort($numeros);
       return $numeros;
   }

}

The requirements cannot be met if the difference between the maximum and minimum is smaller than the quantity, so I did this validation (could have released an exception).

  • Create an array of all possible numbers.
  • Then they are shuffled with the function "shuffle".
  • The first shall be chosen in the specified quantity.
  • Are ordered.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.