Trouver la valeur la plus proche d’une autre en php
L’autre jour, je me baladais sur le web et je suis tombé sur codingame.com. Trouvant le concept sympa, j’ai participé aux exos d’entrainement dont un qui m’a bien plu: il fallait trouver la valeur la plus proche de 0 dans une liste de chiffre.
Au prime abord, ça parait vraiment facile mais au final, non :D. On oublie quelques cas particuliers (comme par exemple, n’avoir que des nombres négatifs ou des nombres identiques etc…).
N’ayant pas (ou peu) trouvé de ressources sur le net (ou pas en php), j’ai décidé d’en faire un article.
Le sujet
Codingame nous pose ces contraintes:
- Afficher 0 si aucune température n’est fournie
- Sinon on affiche la température la plus proche de 0. Si 2 entiers sont aussi proches de 0, on prend l’entier positif. Donc si on a le choix entre -5 et 5, on prend 5.
- Le nombre de températures est compris entre 0 (inclus) et 10000 (non inclus).
- Les valeurs sont fournies, séparées par un espace.
La réflexion
L’exercice étant chronométré, mon code que je proposerai ne sera pas optimal. Vous verrez que j’ai une passion pour les tableaux, j’aime bien tout mettre dans des tableaux 😀
Voilà ma réflexion:
- Mettre les valeurs dans un tableau en se servant de l’espace comme séparateur
- Compter le nombre de valeurs (pour vérifier que le nombre de températures est bien compris entre 0 et 10k)
- Supprimer les doublons (ça sert à rien de se trimballer des chiffres répétés plusieurs fois)
- Créer un tableau associant l’écart de la valeur par rapport à 0 et sa valeur absolue
- Recréer un tableau pour trouver la plus proche de 0 en bouclant => si l’écart (par rapport à 0) est plus petit que le précédent, on l’écrase.
- Vu que on se base que sur l’écart et qu’on doit choisir uniquement le positif, on doit vérifier si une clé positive existe, on la prend sinon on prend la négative
- Bingo?
Le code
Mettre les valeurs dans un tableau en se servant de l’espace comme séparateur
Pour cela on va se servir de « explode »:
<?php //on cree une chaine de valeur $valeurs="-15 -7 -9 -14 -12 -2"; //et on se sert de l'espace pour créer un tableau $explode= explode(" ", $valeurs); ?>
Notre tableau $explode nous retourne désormais:
Array ( [0] => -15 [1] => -7 [2] => -9 [3] => -14 [4] => -12 [5] => -2 )
Compter le nombre de valeurs (pour vérifier que le nombre de températures est bien compris entre 0 et 10k)
Rien de bien compliqué, on utilise « count »:
$n= count($explode); //ici $n retourne 6
Supprimer les doublons (ça sert à rien de se trimballer des chiffres répétés plusieurs fois) et créer un tableau associant l’écart de la valeur par rapport à 0 et sa valeur absolue
En associant l’écart de la valeur par rapport à 0 et sa valeur absolue, on récupère nos valeurs et on supprime les doublons (package):
foreach($explode as $new) { //pour chaque valeur de $explode on recupere sa valeur absolue $abs=abs($new); //et on cree un nouveau tableau $array qui contiendra la valeur "normale" associee a sa valeur absolue $array[$new]=$abs; }
Notre tableau $array retourne:
Array ( [-15] => 15 [-7] => 7 [-9] => 9 [-14] => 14 [-12] => 12 [-2] => 2 )
Recréer un tableau pour trouver la plus proche de 0 en bouclant => si l’écart (par rapport à 0) est plus petit que le précédent, on l’écrase.
On va réutiliser notre $array et créer le tableau final (c’est promis c’est le dernier :)), dans lequel nous mettrons uniquement l’écart. Puis on vérifiera si la dernière valeur est plus proche que la nouvelle. Si oui, on la laisse sinon on la remplace par la nouvelle.
//on cree notre tableau final $tab_final= array(); foreach($array as $ecart) { //on voit si le tableau est vide $count=count($tab_final); //s'il est vide, on injecte la 1ere valeur qui passe if($count==0) { $tab_final[]= $ecart; } //si le dernier element du tab_final est superieur a l'ecart, on crash le tab final et on injecte la nouvelle valeur if($tab_final[0]>$ecart) { $tab_final=array(); $tab_final[]= $ecart; } }
$tab_final nous retourne:
Array ( [0] => 2 )
Comme vous pouvez le voir, on récupère la bonne valeur mais pas le bon signe. Donc passons à la prochaine étape.
Vu que on se base que sur l’écart et qu’on doit choisir uniquement le positif, on doit vérifier si une clé positive existe, on la prend sinon on prend la négative
Tout est dit dans le titre 🙂
//on recupere notre dernier ecart dans $ecartok $ecartok=$tab_final[0]; //si l'ecart positif est ds le tab if (array_key_exists($tab_final[0], $array)) { //si vous voulez faire un traitement particulier } //sinon on prend la valeur negative else { $ecartok *= -1; } //et on affiche notre resultat echo $ecartok;
Et voilà nous avons -2.
Le code final
:
$valeurs="-15 -7 -9 -14 -12 -2 -15"; $explode= explode(" ", $valeurs); $n= count($explode); if ($n>=0 && $n<10000) { foreach($explode as $new) { //pour chaque valeur de $explode on recupere sa valeur absolue $abs=abs($new); //et on cree un nouveau tableau $array qui contiendra la valeur "normale" associee a sa valeur absolue $array[$new]=$abs; } //on cree notre tableau final $tab_final= array(); foreach($array as $ecart) { //on voit si le tableau est vide $count=count($tab_final); //s'il est vide, on injecte la 1ere valeur qui passe if($count==0) { $tab_final[]= $ecart; } //si le dernier element du tab_final est superieur a l'ecart, on crash le tab final et on injecte la nouvelle valeur if($tab_final[0]>$ecart) { $tab_final=array(); $tab_final[]= $ecart; } } //on recupere notre dernier ecart dans $ecartok $ecartok=$tab_final[0]; //si l'ecart positif est ds le tab if (array_key_exists($tab_final[0], $array)) { } //sinon on prend la valeur negative else { $ecartok *= -1; } //et on affiche notre resultat echo $ecartok; } //si on a aucune temperature on affiche 0 elseif($n==0) { echo 0; }
Voici quelques exemples pour tester:
-15 -7 -9 -14 -12
-15 -7 -9 -14 -12 7
12 -15 -7 -9 -14 -12
-10 -10
15 -7 9 14 7 12
7 5 9 1 4
Il manquerait pas une suite?
Et là vous vous dites : et comment je fais si je veux comparer mes chiffres à autre chose que 0? Le titre de l’article dit bien: « Trouver la valeur la plus proche d’une autre » et non « Trouver la valeur la plus proche de 0 ». Je vais me plaindre à mon syndicat etc…
Et vous auriez bien raison si j’arrêtais l’article ici mais je vous propose tout de suite un autre bout de code pour comparer vos chiffres à autre chose que 0.
J’avoue avoir simplifier au max le code, j’aime bien mes tableaux mais une fois suffit :D.
Trouver la valeur la plus proche d’une autre (enfin)
En effet, j’ai simplifié au max le code en utilisant ksort une fonction bien utile. Ça vous permettra de voir 2 façons de faire.
Alors attention avec cette méthode, si vous choisissez 10 comme chiffre à comparer et que vous avez 9 et 11 dans votre liste de valeurs, le code prendra le dernier de la liste (donc 11).
Le code tant attendu
On reprend notre base et on cree notre variable $notre_chiffre symbolisant notre chiffre choisi:
$valeurs="15 7 9 14 -7 12"; $explode= explode(" ", $valeurs); $n= count($explode); $notre_chiffre= 8;
Puis nous créons un tableau avec la valeur absolue de l’écart qu’on associe au chiffre de la liste tout simplement:
foreach($explode as $new) { //on cree une variable qui sera notre ecart en valeur absolue $abs=abs($new-$notre_chiffre); //et on cree un nouveau tableau $array qui contiendra la valeur "normale" associee a son ecart par rapport au nombre choisi en valeur absolue (ou plutot l'inverse) $array[$abs]=$new; }
A cette étape, $array retourne:
Array ( [7] => 15 [1] => 9 [6] => 14 [15] => -7 [4] => 12 )
On va trier les clés du tableau avec ksort:
//on trie les clés ksort($array);
Desormais, notre tableau $array retourne:
Array ( [1] => 9 [4] => 12 [6] => 14 [7] => 15 [15] => -7 )
Donc le 9 est le plus proche de notre chiffre choisi (ici le 8) et a un écart de 1.
Comme ça, on ne peut pas utiliser $array[0] pour récupérer la première valeur du tableau donc on va utiliser current:
//on recupere le premier element du tableau $array $ecartok=current($array); //et on affiche notre resultat echo $ecartok;
Et voilà, $ecartok nous retourne bien 9.
Le code complet
<?php $valeurs="15 7 9 14 -7 12"; $explode= explode(" ", $valeurs); $n= count($explode); $notre_chiffre= 8; if ($n>=0 && $n<10000) { foreach($explode as $new) { //on cree une variable qui sera notre ecart en valeur absolue $abs=abs($new-$notre_chiffre); //et on cree un nouveau tableau $array qui contiendra la valeur "normale" associee a son ecart par rapport au nombre choisi en valeur absolue (ou plutot l'inverse) $array[$abs]=$new; } //on trie les clés dans l'ordre croissant ksort($array); //on recupere le premier element du tableau $array $ecartok=current($array); //et on affiche notre resultat echo $ecartok; } elseif($n==0) { echo 0; } ?>
C’est déjà bien plus sympa que le précédent code non? 😉
Si vous avez apprécié cet article, n’hésitez pas à le partager sur les réseaux sociaux et/ou de laisser un commentaire ci dessous.
Bon dev à vous 😉
3 réflexions au sujet de « Trouver la valeur la plus proche d’une autre en php »
Temps approximatif pour la lecture des commentaires : 7 mins-
Sow Le 9 janvier 2018 à 23 h 49 min
|
-
guillaume RICHARD Le 15 juillet 2018 à 9 h 45 min
|
-
Break Le 17 mai 2022 à 14 h 49 min
|
Salut camarade développeur voici le traitement que je propose pour n’importe quelle tableau de valeurs positives et/ou négatives contenant bien entendu la valeur 0.
Le traitement peut être amélioré pour traiter les cas pour des tableaux ne contenant pas la valeur 0.
Salut,
Cet article est intéressant car tu expliques de A à Z comment tu développes ton code.
Même si tu dis avoir fait ce code dans un temps donné, je pense avoir déceler une erreur dans ton code.
Tu veux vérifier si un écart positif existe dans le tableau, avec le code suivant :
Le problème, est que cette fonction vérifie si une clé existe dans un tableau, pas les valeurs de ce tableau.
Pour cela, il faut utiliser la fonction in_array :
Qu’en penses-tu ?