Utilisation des boucles ou fct récursives ?

Mammouth du PHP | 536 Messages

29 févr. 2008, 15:31

Bonjour à tous,

je viens vous demander de m'aider car là je bloque un peu.
Je travaille sur un calcul de frais de port et voici l'algorithme que je n'arrive à traduire en php :
<?
// ========== EXPLICATION DE L'ALGORITHME ================
/*****************************************************************
* Tant que le poids restant est > 10KG 
* On classe le poids des articles par ordre décroissant 
* On fait des paquets de 10KG en partant du poids le plus élevé (n)
* Ensuite, on prend l'article dont le poids est juste aud essus (plus léger, n-1 
* Si avec cet article (n-1), on peut faire un article de max 10kg,
*   alors on l'ajoute au colis 
* On regarde ensuite si on peut ajouter l'article n-2, n-3, n-n... 
* Sinon, si on ne peut ajouter l'article ?  
*   alors on regarde si on peut ajouter l'article n-2, si on peut pas n-3... n-n 
******************************************************************/
?>
Et de mon côté voici le code que j'ai fait pour l'instant arpès de nombreux essais.
<?
echo "nbre articles : ".count($nb_article_moins_10)."<br />";
                          for($i=0; $i<count($nb_article_moins_10); $i++){
                            echo "poids article : ".$nb_article_moins_10[$i]['poids']."<br />";
                            echo "qte article : ".$nb_article_moins_10[$i]['quantite']."<br />";
                            $qte_article = $nb_article_moins_10[$i]['quantite'];
                            for($j=0; $j<=$qte_article; $j++){
                              $poids_colis += str_replace(",",".",$nb_article_moins_10[$i]['poids']);
                              if($poids_colis > 10){
                                $poids_colis -= str_replace(",",".",$nb_article_moins_10[$i]['poids']);
                                break;
                              }
                              else{
                                $nb_article_moins_10[$i]['poids']--;
                              }
                              echo $poids_colis;
                            }
                          }
?>
Ici nb_article_moins_10 est un tableau dans lequel se trouve les produits dont le poids est < 10 kg et la quantité commandée de ces produits.

Ce que je dois faire, c'est calculer un frais de port en répartissant les articles dans des colis de 10kg maximum.
Sachant que :
un article de 7 kg et deux articles de 3,5kg = 2 colis de 7kg
deux articles de 8 kg = 2 colis de 8kg
4 articles de 2 kg plus 1 article de 1.5kg = 1 colis de 9.5kg...

Pouvez vous m'aidez ?

Voici un code que j'avais fait auparavant mais qui ne correspondait pas puisqu'avaec ce code on aait :
un article de 7 kg et deux articles de 3,5kg = 1 colis de 10kg et un colis de 0.5kg
<?
// ANCIEN CODE QUI NE FONCTIONNE PAS :
                          $nb_colis_10_kg = floor($poids_restant/10);
                          connexion();
                          $tnt = mysql_query("SELECT * FROM frais_port WHERE port_a > 10 AND port_de <= 10") or die(mysql_error());
                          $res_tnt = mysql_fetch_array($tnt);
                          $resultat_fp2 += $res_tnt['tarif_z'.$zone];
                          $poids_restant = ($poids_restant - (10*$nb_colis_10_kg)); //le nouveau poids restant = poids restant - poids de tous les colis de 10kg qu'on a pu faire
                          deconnexion();
                          // FIN DE ANCIEN CODE
?>
Modifié en dernier par béka le 04 mars 2008, 11:07, modifié 1 fois.
Un prof désespéré à son élève :
- Et maintenant, dessinez-moi un cercle au tableau... Voila... Alors qu'est-ce que c'est?
- Ben un cercle ?
- Non, c'est votre note, sortez !!

Mammouth du PHP | 1353 Messages

29 févr. 2008, 15:51

Bonjour,

pourquoi ne pas suivre l'algorithme proposé ?

1/ Trier le tableau grâce au fonction de tri php (en l'occurence usort() pour un tableau multidimensionnel)

2/ Commencer avec l'objet le plus lourd et tester dans la boucle avant d'ajouter l'article si l'un + l'autre >10... faire ainsi de suite avec tout les articles et les retirer du tableau au fur et à mesure...
Tell me and I forget. Teach me and I remember. Involve me and I learn.

Mammouth du PHP | 536 Messages

29 févr. 2008, 16:10

oui mais justement c'est ça que je n'arrive pas à faire. Je suppose qu'il serait mieux d'utiliser des fonctions récursives, mais comment faire ?

PS : mon tableau est déjà trié puisque dedans il y a les résultats d'une requête SQL qui avait déjà été triée avec un ORDER BY DESC
Un prof désespéré à son élève :
- Et maintenant, dessinez-moi un cercle au tableau... Voila... Alors qu'est-ce que c'est?
- Ben un cercle ?
- Non, c'est votre note, sortez !!

ViPHP
ViPHP | 4674 Messages

29 févr. 2008, 16:18

Juste une intervention.

Les fonctions récursives ne sont pas forcément plus rapide, mais consomme plus de mémoires. Si tu es au stade de chipoter entre les 2, alors commence par simplifier d'autres choses (comme le count dans ton for ...).

La récursivité peut être utile pour arriver à des complexités log n ou des choses du genre (je ne rentre pas dans les détails), mais tu as sûrement moyen de faire avec les fonctions de PHP qui seront plus rapides.
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Mammouth du PHP | 536 Messages

29 févr. 2008, 16:43

Certainement et je préfèrerais mais là je bloque.
Un prof désespéré à son élève :
- Et maintenant, dessinez-moi un cercle au tableau... Voila... Alors qu'est-ce que c'est?
- Ben un cercle ?
- Non, c'est votre note, sortez !!

Mammouth du PHP | 1353 Messages

29 févr. 2008, 16:51

je ne sais pas exactement mais un truc dans ce genre pourrait etre une bonne piste :
while(poids_total($tableau) > 10)
	{
	for($i=0;$i<count($tableau);$i++)
		{
		if($tableau[$i]["quantité"])
			{
			nouveau_colis();
			ajouter_au_colis($tableau[$i]);
			$poids_colis = $tableau[$i]["poids"]
			
			for($j=0;$j<count($tableau);$j++)
				{
				if($poids_colis+$tableau[j]["poids"]<=10)
					{
					$poids_colis += $tableau[j]["poids"];
					$tableau[j]["quantité"]--;
					ajouter_au_colis($tableau[j]);
					}
				}
		}
	}
à voir, je ne sais pas si le while est utile j'ai plus trop le temps mais sinon avec ce genre de procédure et une fonction nouveau_colis et ajouter_au_coulis qui font ce qu'elles doivent faire (écriture en base, création de variables...) je pense que ca peut marcher... A voir ;)
Tell me and I forget. Teach me and I remember. Involve me and I learn.

ViPHP
ViPHP | 4674 Messages

29 févr. 2008, 16:55

C'est déjà un début.
Mais il faudrait penser à sortir les count des for (les mettres en variable avant), ce sera plus efficace ...
« Un handicap est le résultat d'une rencontre entre une déficience ou différence et une incapacité de la société à répondre à celle-ci. »

Hoa : http://hoa-project.net (sur @hoaproject).

Mammouth du PHP | 536 Messages

29 févr. 2008, 17:04

je regardes et essaie de mon côté en considérant toutes vos indications et remarques.
Je tiens au courant d'une évolution.
Un prof désespéré à son élève :
- Et maintenant, dessinez-moi un cercle au tableau... Voila... Alors qu'est-ce que c'est?
- Ben un cercle ?
- Non, c'est votre note, sortez !!

Mammouth du PHP | 536 Messages

03 mars 2008, 12:51

bonjour tout le monde,

je bloque toujours sur le même points.
je n'arrive pas à faire en sorte de faire des paquets de 10kg sur mes produits suivant l'algorithme de mon premier commentaire.

Aujourd'hui, voici a quoi ressemble mon code :
<?
while($quantite_totale > 0){
   for($i=0; $i<$nombre_moins_10; $i++){ //pour chacun des articles
          echo "poids article : ".$nb_article_moins_10[$i]['poids']."<br />"; //on récupère le poids
          echo "qte article : ".$nb_article_moins_10[$i]['quantite']."<br />"; //et la qte commandée
                   for($j=0; $nb_article_moins_10[$i]['quantite']==0; $j++){ //pour chaque quantite commandée
                         $poids_colis += $nb_article_moins_10[$i]['poids'];
                         if($poids_colis > 10){
                              $poids_colis -= $nb_article_moins_10[$i]['poids'];
                          }
                          else{
                                 $nb_article_moins_10[$i]['quantite']--;
                                  $quantite_totale --;
                                    $tnt = mysql_query("SELECT * FROM frais_port WHERE port_a > ".$poids_colis." AND port_de <= ".$poids_colis) or die(mysql_error());
                                    $res_tnt = mysql_fetch_array($tnt);
                                    $resultat_fp9 += $res_tnt['tarif_z'.$zone];
                            }
                     }
    }
}
?>
En amont de ce srcipt j'ai ceci dans une boucle :
<?
$nb_article_moins_10[$g]['poids'] = str_replace(",",".",$res_panier['poids']);
$nb_article_moins_10[$g]['quantite'] = $res_panier['qte'];
$g++;
$quantite_totale += $res_panier['qte'];
?>
et
<?
$tnt = mysql_query("SELECT * FROM frais_port WHERE port_a > ".$poids_colis." AND port_de <= ".$poids_colis) or die(mysql_error());
$res_tnt = mysql_fetch_array($tnt);
$resultat_fp9 += $res_tnt['tarif_z'.$zone];
?>
me permet de récupérer le tarif qui sera appliqué dans une base.

Pouvez-vous m'adier ?
Un prof désespéré à son élève :
- Et maintenant, dessinez-moi un cercle au tableau... Voila... Alors qu'est-ce que c'est?
- Ben un cercle ?
- Non, c'est votre note, sortez !!

Mammouth du PHP | 536 Messages

04 mars 2008, 11:03

Bonjour,

je suis parti du script de guilt92 afin de faire ceci :
<?
while($quantite_totale > 0) {
        for($i=0;$i<count($nb_article_moins_10);$i++) {
             if($nb_article_moins_10[$i]["quantite"]) {
                $poids_colis = $nb_article_moins_10[$i]["poids"];
                 echo count($nb_article_moins_10);
                 for($j=0;$j<count($nb_article_moins_10);$j++) {
                      if($poids_colis+$nb_article_moins_10[$j]["poids"]<=10) {
                        $poids_colis += $nb_article_moins_10[$j]["poids"];
                        $nb_article_moins_10[$j]["quantite"] = $nb_article_moins_10[$j]["quantite"] - 1;
                         //ajouter_au_colis($nb_article_moins_10[$j]);
                         //on récupère ici le frais de port calculé pour ce colis
                         connexion();
                         $tnt = mysql_query("SELECT * FROM frais_port WHERE port_a > ".$poids_colis." AND port_de <= ".$poids_colis) or die(mysql_error());
                          $res_tnt = mysql_fetch_array($tnt);
                          deconnexion();
                          $resultat_fp9 = $res_tnt['tarif_z'.$zone];
                          //fin de frais de port
                          echo "poids du colis : ".$poids_colis."&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;frais calculés : ".$resultat_fp9."<br />";
                           $quantite_totale = $quantite_totale - 1;
                           if($quantite_totale == '0') { break; }
                         }
                    }
              }
        }
}
?>
Mais en faisant ceci, je n'obtiens toujours pas le résultat souhaité pourtant j'ai le sentiment de ne pas être loin.
De ce façon (ci-dessus), je n'ai pas lorsque je commande 5 produits de 3,5kg 2 colis de 7kg et 1 colis de 3,5kg mais j'affiche 5 fois un colis de 7kg.

Pouvez-vous m'aider ?