Hier, le 10 août 2012, un britannique a remporté le plus gros gain du célèbre jeu de loterie européen : la bagatelle de 190 millions d’euros. De quoi s’offrir de belles choses. Cela faisait 10 tirages consécutifs que personne n’avait réussi à trouver les 5 bons numéros parmi les 50 et les 2 étoiles parmi les 11. Et pourtant, beaucoup de personnes jouent ? Il devrait y avoir un moyen ? Et bien en se basant sur les mathématiques, la probabilité d’avoir ces 5 numéros et ces 2 étoiles n’est que de 0,000 000 858 %. Pour autant, le phénomène de société du “et pourquoi pas moi ?” fait que l’Euromillions reste un jeu très populaire, plus encore quand la cagnotte atteint son plafond de 190 millions.
Etudions un petit peu ce jeu, d’un point de vue des probabilités. Je vous propose ensuite un petit code PHP qui permet de générer des grilles d’Euromillions et d’en sortir quelques statistiques intéressantes. Hier, je me suis amusé à tirer 100 000 grilles aléatoirement. Et bien figurez-vous que je n’ai pas trouvé la bonne combinaison !
Probabilités
Pour calculer les différentes probabilités d’atteindre les différents rangs de gain de l’Euromillions, on utilise les combinaisons (l’ordre de sortie des numéros ne compte pas).
Ainsi la probabilité d’obtenir les 5 bons numéros et les 2 bonnes étoiles est donnée par la formule :
Soit de 1 chance sur 116 531 800.
Voici un tableau qui résume les probabilités pour les différents rangs, trouvé sur Wikipédia :
En résumé, une personne aura 7,81 % de chance (soit environ une chance sur treize) de remporter un gain sur chaque combinaison jouée à 2 € la combinaison. À titre de comparaison, au Loto, un joueur a 16,7 % de chance (environ une chance sur six) de remporter un gain sur une combinaison simple.
Code PHP
Le code PHP suivant permet d’effectuer un tirage aléatoire d’une grille d’Euromillions. Les résultats sont ensuite enregistrés dans une base de données, pour un futur traitement. A noter qu’avant d’être enregistré, les nombres et les étoiles du tirage sont rangés dans un ordre croissant, ceci afin de faciliter la sélection dans la table plus tard. Le code PHP devrait être suffisamment commenté (en anglais !) pour que vous le compreniez facilement.
<?php | |
/* CONFIGURATION */ | |
$host = 'localhost'; | |
$user = 'root'; | |
$password = 'root'; | |
$db_name = 'euromillions'; | |
$time_to_play = 10000; | |
/* END OF CONFIGURATION */ | |
/* If you edit something below, the sky will fall on you. Yeah, it's true. Don't try. */ | |
mysql_connect($host, $user, $password); | |
mysql_select_db($db_name); | |
function microtime_float() | |
{ | |
list($usec, $sec) = explode(" ", microtime()); | |
return ((float)$usec + (float)$sec); | |
} | |
function generateNumber() | |
{ | |
return mt_rand(1, 50); | |
} | |
function generateStar() | |
{ | |
return mt_rand(1, 11); | |
} | |
function insertDB($stats_number, $stats_star, $array_numbers, $array_stars) | |
{ | |
// Sort arrays. Elements will be arranged from lowest to highest (values). | |
sort($array_numbers); | |
sort($array_stars); | |
// Numbers. | |
for ($i=1;$i<=5;$i++) | |
{ | |
$name_var = 'nb_'.$i; | |
${$name_var} = $array_numbers[$i-1]; | |
// Stats | |
$stats_number[$array_numbers[$i-1]] += 1; | |
} | |
// Stars. | |
for ($i=1;$i<=2;$i++) | |
{ | |
$name_var = 'star_'.$i; | |
${$name_var} = $array_stars[$i-1]; | |
// Stats | |
$stats_star[$array_stars[$i-1]] += 1; | |
} | |
// Insert into the DB. | |
$query = mysql_query("INSERT INTO euromillions (nb_1, nb_2, nb_3, nb_4, nb_5, star_1, star_2) VALUES ('$nb_1', '$nb_2', '$nb_3', '$nb_4', '$nb_5', '$star_1', '$star_2')"); | |
// We need to always return arrays in order to deal with stats at the end | |
return array($stats_number, $stats_star); | |
} | |
function initialize() | |
{ | |
// Initialize arrays for stats | |
$stats_number = array(); | |
$stats_star = array(); | |
for ($i=1;$i<=50;$i++) | |
{ | |
$stats_number[$i] = 0; | |
} | |
for ($i=1;$i<=11;$i++) | |
{ | |
$stats_star[$i] = 0; | |
} | |
// We need to always return arrays in order to deal with stats at the end | |
return array($stats_number, $stats_star); | |
} | |
function play($stats_number,$stats_star) | |
{ | |
$array_numbers = array(); | |
$array_stars = array(); | |
for ($i=1;$i<=7;$i++) | |
{ | |
if ($i >= 1 AND $i <= 5) // Numbers. | |
{ | |
do | |
{ | |
$number = generateNumber(); | |
} while (in_array($number, $array_numbers)); | |
// We haven't got the number in the array, let's insert it. Array starts at 0. | |
$array_numbers[$i-1] = $number; | |
} | |
else // Stars | |
{ | |
do | |
{ | |
$star = generateStar(); | |
} while (in_array($star, $array_stars)); | |
// We haven't got the star in the array, let's insert it. Array starts at 0. | |
$array_stars[$i-6] = $star; | |
} | |
} | |
// Everything is ok, let's insert in the DB | |
$data = insertDB($stats_number,$stats_star, $array_numbers, $array_stars); | |
// We need to always return arrays in order to deal with stats at the end | |
return array($data[0], $data[1]); | |
} | |
function hardcoreGamer($time_to_play) | |
{ | |
// Initialize arrays for stats before we play | |
$data = initialize(); | |
$stats_number = $data[0]; | |
$stats_star = $data[1]; | |
if ($time_to_play < 1 OR !is_integer($time_to_play)) // Never trust user input | |
{ | |
$time_to_play = 1; | |
} | |
for ($i=1;$i<=$time_to_play;$i++) | |
{ | |
$data = play($stats_number,$stats_star); | |
$stats_number = $data[0]; | |
$stats_star = $data[1]; | |
} | |
// We need to always return arrays in order to deal with stats at the end | |
return array($stats_number, $stats_star); | |
} | |
function displayStats($stats_number, $stats_star, $time_start, $time_to_play) | |
{ | |
// Sort arrays. From highest to lowest. We need to keep keys within the array with a descending sort for values so we use the arsort function. | |
arsort($stats_number); | |
arsort($stats_star); | |
echo '<div style="width:700px">'; | |
echo '<hr/>'; | |
echo '<h1>Most common numbers</h1>'; | |
print_r($stats_number); | |
echo '<hr />'; | |
echo '<h1>Most common stars</h1>'; | |
print_r($stats_star); | |
echo '<hr/>'; | |
echo '<h1>Time</h1>'; | |
$time_end = microtime_float(); | |
$time = round($time_end - $time_start, 8); | |
$nb_tests_per_second = round($time_to_play / $time); | |
echo $time_to_play.' tests executed in '.$time.'s. That is to say '.$nb_tests_per_second.' tests per second.'; | |
echo '</div>'; | |
} | |
// Start the chrono | |
$time_start = microtime_float(); | |
// We play | |
$data = hardcoreGamer($time_to_play); | |
// We display stats | |
displayStats($data[0], $data[1], $time_start, $time_to_play); |
Et voici le code SQL permettant de créer la table associée au précédent code :
CREATE TABLE `euromillions` ( | |
`id` int(10) NOT NULL AUTO_INCREMENT, | |
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, | |
`nb_1` int(2) NOT NULL, | |
`nb_2` int(2) NOT NULL, | |
`nb_3` int(2) NOT NULL, | |
`nb_4` int(2) NOT NULL, | |
`nb_5` int(2) NOT NULL, | |
`star_1` int(2) NOT NULL, | |
`star_2` int(2) NOT NULL, | |
PRIMARY KEY (`id`) | |
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1; |
Vous obtiendrez quelque chose de cette forme après avoir lancé le code PHP :