Combinação e sorteio de números com PHP
Neste artigo vamos ver exemplos práticos de combinação e sorteio de números utilizando a linguagem PHP. Nestes exemplos vamos trabalhar com manipulação de arrays e cálculo de fatoriais.
O primeiro problema que vamos resolver é um problema de combinação. Dado uma certa quantidade de números e um tamanho fixo, vamos criar uma lista com todas as combinações possíveis.
function combinacoesDe($k, $xs){
if ($k === 0)
return array(array());
if (count($xs) === 0)
return array();
$x = $xs[0];
$xs1 = array_slice($xs,1,count($xs)-1);
$res1 = combinacoesDe($k-1,$xs1);
for ($i = 0; $i < count($res1); $i++) {
array_splice($res1[$i], 0, 0, $x);
}
$res2 = combinacoesDe($k,$xs1);
return array_merge($res1, $res2);
}
$dezenas = array("2", "4", "5", "6", "7", "9", "10", "12", "15", "16", "18", "20", "21", "22", "23", "24", "25");
print_r(combinacoesDe(14,$dezenas));
No exemplo anterior, utilizamos um array com 17 números, e o nosso objetivo foi gerar como saída combinações compostas por apenas 14 números. A função combinacoesDe usa recursão para gerar as combinações. Ela divide o problema em subproblemas menores, combinando elementos de forma recursiva. Seu resultado foi um array com 680 registros.
A função combinacoesDe fez utilização de 3 funções de manipulação de arrays do PHP, que foram:
ARRAY_SLICE() - Esta função retorna uma parte de um array, sem modificar o array original. Ela recebe pelo menos dois parâmetros: O array original e o índice de início, que define onde o fatiamento vai começar.
ARRAY_SPLICE() - Esta função remove ou substitui uma parte do array original. Ela recebe pelo menos três parâmetros: O array original, o índice de início onde vai começar a modificação e o número de elementos a remover.
ARRAY_MERGE() - Esta função junta dois ou mais arrays em um só , mantendo a ordem dos elementos.
Vamos ver um segundo exemplo. Como sortear uma determinada quantidade de números. No exemplo a seguir, temos um array com 12 números, e vamos sortear 5.
$qtd = 5;
$input = array(1,2,3,4,5,6,7,8,9,10,11,12);
$rand_keys = array_rand($input, $qtd);
for($x=0;$x<$qtd;$x++){
echo $input[$rand_keys[$x]] . "<br>";
}
No exemplo utilizamos um laço de repetição for que vai ser iterado 5 vezes, que é a quantidade de números que desejamos sortear. Antes de fazer a interação, alteramos o nosso array utilizando a função array_rand(). A função array_rand() é usada para selecionar uma ou mais chaves aleatórias de um array. Seu primeiro parâmetro é um array, o segundo é a quantidade de chaves aleatórias desejadas.
No exemplo a seguir vamos simular a geração de volantes para apostas numa loteria.
function numeros_loteria($min, $max, $qtd) {
$numeros = range($min, $max);
shuffle($numeros);
return array_slice($numeros , 0, $qtd);
}
var_dump(numeros_loteria(1,25,15));
Neste exemplo, criamos um volante com 15 números, selecionando números entre 1 a 25. A função auxiliar numeros_loteria utilizou 3 funções para fazer esta seleção:
RANGE() - Esta função gerou um array com base num número inicial e final.
ARRAY_SLICE() - Esta função retorna uma parte de um array, sem modificar o array original. Ela recebe pelo menos dois parâmetros: O array original e o índice de início, que define onde o fatiamento vai começar.
SHUFFLE() - Esta função é utilizada para embaralhar os elementos de um array de forma aleatória. Ela altera o array original, sem necessidade de criar um novo array.
Com base nesta função auxiliar, podemos criar vários volantes, basta chamar esta função dentro de um laço de repetição for.
$qtd_jogos = 50;
for($x=0;$x<$qtd_jogos;$x++){
echo "<h3>JOGO ".($x+1).":</h3> ";
var_dump(numeros_loteria(1,25,15));
echo "<hr>";
}
Para nosso último exemplo, vamos ver o cálculo de probabilidades de uma determina sequência numérica ser sorteada. Com base num intervalo de 60 números, desejamos apostar 7 números e queremos calcular qual a possibilidade de acertar 6 números sorteados.
$a = 60; // Números no total
$b = 6; // Dezenas que serão sorteadas
$k = 7; // Irei apostar com 7 números
$i = 6; // Acertos pretendidos
// Realizando as subtrações
$c1 = $a - $k;
$c2 = $b - $i;
$calculo_1 = gmp_fact($c1) / (gmp_fact($c2) * gmp_fact(($c1 - $c2)));
$calculo_2 = gmp_fact($k) / (gmp_fact($i) * gmp_fact(($k - $i)));
$calculo_3 = gmp_fact($a) / (gmp_fact($b) * gmp_fact(($a - $b)));
$calculo_4 = $calculo_1 * $calculo_2;
$calculo_final = $calculo_3 / $calculo_4;
echo "Probabilidade de acerto " . $calculo_final;
Para ajudar a resolver o problema foi utilizada a função gmp_fact(). A função gmp_fact() é usada para calcular o fatorial de um número inteiro grande. Um número fatorial de um número inteiro positivo "n" e ele é o produto de todos os inteiros positivos de 1 até "n".
Esta função faz parte da extensão GMP (GNU Multiple Precision) e permite trabalhar com números inteiros que podem ser muito grandes, além do limite dos inteiros padrão do PHP.
Ao executar o código, vimos que a possibilidade de acertar 6 números num intervalo de 60 é de 7.151.980