Números aleatorios sin duplicación usando una matriz en PHP

Estoy tratando de crear un generador de números aleatorios en PHP. Se supone que genera tres (3) números a la vez, sin repetición. Es decir, los 3 números no pueden ser los mismos.

Esto es lo que he intentado hasta ahora:

$array = []; $A = mt_rand(1,36); $array[0] = $A; $B = mt_rand(1,36); $array[1] = $B; if(in_array($B,$array)){ $B = mt_rand(1,36); $array[1] = $B; } $C = mt_rand(1,36); $array[2] = $C; if(in_array($C,$array)){ $C = mt_rand(1,36); $array[2] = $C; } $length = count($array); //display the array values; for($i = 0; $i < $length; $i++){ echo ($array[$i]."
"); }

¿Alguien puede decirme a dónde me voy mal?

Como este (según mi comentario inicial),

 $array = []; while( count($array) < 3 ){ $rand = mt_rand(1,36); $array[$rand] = $rand; } print_r( $array ); 

Al configurar la "clave" para que sea el número aleatorio, podemos abusar del hecho de que las claves de matriz asociativa son únicas. Entonces es una simple cuestión de esperar hasta que la matriz contenga la cantidad deseada de elementos únicos.

Puedes probarlo aquí

Resultados: (tus resultados pueden variar, es aleatorio)

 Array ( [16] => 16 [20] => 20 [27] => 27 ) 

ACTUALIZACIÓN Estaba tratando de pensar en una forma válida de hacerlo sin usar un bucle (en mi camino a casa desde el trabajo), y de esta manera puede ser incluso mejor en algunos casos.

 $a = range(1,36); shuffle($a); $array = array_slice($a, 0, 3); print_r($array); 

Esto tendrá un mejor rendimiento cuando el número de elementos que debes encontrar sea mayor. Esto es porque no hay repetición, no hay colisiones. Así que si tiene un rango pequeño pero necesita encontrar muchos artículos para la devolución, esto se realizará mejor. Si tiene muchos artículos y necesita devolver solo algunos, entonces el primero puede ser mejor, si no es por la velocidad, entonces por el uso de la memoria.

Puedes verlo aquí

Para referencia este usa

range () - Crea una matriz que contiene un rango de elementos.

http://php.net/manual/en/function.range.php

shuffle () - Shuffle (aleatoriza el orden de los elementos en) una matriz. Utiliza un generador de números pseudoaleatorios que no es adecuado para fines criptográficos.

http://php.net/manual/en/function.shuffle.php

array_slice (): devuelve la secuencia de elementos de la matriz según lo especificado por los parámetros offset y length.

http://php.net/manual/en/function.array-slice.php

Así que para explicar esto último

  • Primero creamos una matriz que contiene cada uno de nuestros posibles números como un elemento. Así, por ejemplo, como este [1,2,3,4,5,6, ...] .
  • A continuación, lo mezclamos aleatoriamente, ordenando el conjunto de la matriz. Shuffle modifica la matriz por "referencia", por lo que no devuelve nuestra matriz y, por lo tanto, no hay ninguna asignación (creo que devuelve Boolean, sin embargo, no sé cómo podría fallar y devolver falsa, más o menos devuelve true con lo que no queremos sobrescribir nuestra matriz con). Entonces nuestro ejemplo se convierte en este [16,20,27,14,5,1, ...]
  • Por último, eliminamos la cantidad de artículos que necesitamos devolver. Finalmente terminamos el ejemplo con esto [16,20,27] ;

Puede reducir la primera línea en una línea (en realidad 2) asignando el valor de la variable $rand en la condición del bucle. Me gusta esto:

 $array = []; while( count($array) < 3 && false !== ($rand = mt_rand(1,36))) $array[$rand] = $rand; 

Porque mt_rand(1,36) nunca devolverá boolan false. Además, si recuerdo que mt_rand es el mismo que rand ahora, o al menos en las versiones actuales de PHP.

Nota: A partir de PHP 7.1.0, rand () usa el mismo generador de números aleatorios que mt_rand (). Para preservar la compatibilidad con versiones anteriores, rand () permite que max sea más pequeño que min en lugar de devolver FALSE como mt_rand (). http://php.net/manual/en/function.rand.php

Espero que te ayude, recuerda pensar fuera de la caja.