Modification d'un algo de calculs de somme

Répondre


Cette question est un moyen d’empêcher des soumissions automatisées de formulaires par des robots.
Smileys
:D :) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :wink: :!: :?: :idea: :arrow: :| :mrgreen: =D> #-o =P~ :^o :non: :priere: 8-|
Voir plus de smileys
  Revue du sujet
 

  Étendre la vue Revue du sujet : Modification d'un algo de calculs de somme

Re: Modification d'un algo de calculs de somme

par Nico » 19 juin 2011, 20:58

J'viens de piger le truc !

Merci beaucoup de ton aide.

Résolu !

Re: Modification d'un algo de calculs de somme

par epommate2 » 18 juin 2011, 14:03

Si on a 1,2,3,4 et 5 comme numéro.

Si on cherche a faire 4 avec un numéro, c'est facile 4 € [1,2,3,4,5]

Si on cherche a faire 7 avec deux numéro :
- on cherche a faire 7 - 1 = 6 avec un numéro (KO)
- on cherche à faire 7 - 2 = 5 avec un numéro (OK)
...
- on cherche à faire 7 - 5 = 2 avec un numéro (OK)

Les solutions sont donc 2+5; 3+4; 4+3 et 5+2. (on trie et on prend à chaque fois les somme uniques => il ne reste que 2+5 et 3+4)

Si on cherche à faire 8 avec trois numéro :
- on cherche a faire 8 -1 = 7 avec deux numéro
- on cherche à faire 8 -2 = 6 avec deux numéro

etc...

Re: Modification d'un algo de calculs de somme

par Nico » 18 juin 2011, 12:57

Humm.. je vais essayer de prendre de bien plus petits chiffres et débugger un peu toutes les valeurs pour comprendre en parallèle de ton explication, car j'ai du mal à comprendre.

Je dois surement manquer de connaissance théorique ou je sais quoi, car je ne comprends pas le principe, on veut additionner des nombres entre eux, et je ne vois aucune addition (visuellement) ni même pourquoi on réduit la somme par un numéro, "je ne comprends pas le rapport", sur les faits je vois l'efficacité, mais en me penchant sur le code et ton explication, c'est encore plus flou..

Re: Modification d'un algo de calculs de somme

par epommate2 » 18 juin 2011, 12:15

Bon, ok, je vais essayer d'expliquer l'algo.

La fonction "trouve" prend en argument un ensemble de numéro, une somme à trouver et un nombre de numéro ($nb_max).

Je fais ce qu'on appelle une récursion. C'est à dire, que, je sais :
- d'une part résoudre le problème dans un cas très simple (1)
- d'autre part simplifier le problème plus compliqué vers un cas plus simple, jusqu'au cas très simple que je sais résoudre. (2)

Pour (1), le cas que je sais résoudre, c'est :
-> Trouver une somme X avec 1 seul numéro dans un tableau

Pour (2), la récursion proprement dite :
->Trouver une somme X avec N numéro dans un tableau, c'est comme trouver, pour chacun des numéro Y du tableau , X - Y avec N -1 numéro

Ma récursion (2) va progressivement me ramener au cas 1.
je suppose que le secret dans la réalisation des algos, c'est.. pratiquer, pratiquer et pratiquer ?
Dans ce cas, je te conseille de ne pas faire du PHP pour apprendre a faire ce type d'algorithme, mais de te tourner vers des langages comme le LISP ou le Prolog. D'ailleurs, je pense que ton problème serait plus vite résolu en LISP.

Re: Modification d'un algo de calculs de somme

par Nico » 18 juin 2011, 11:08

<?php 

set_time_limit(0);

$somme_a_trouver = 114;
$nb_element_max = 5;
$all_numero = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40);

function super_unique($array) {
  $result = array_map("unserialize", array_unique(array_map("serialize", $array)));
  return $result;
}

function trouve($all_numero,$somme,$nb_max){

		// suppose que cela ne sert qu'a titre de debug/information et que tu aurais pu prendre n'importe qu'elle chiffre du nb d'element max.
        if ($nb_max == 4){
                static $test;
                $test++;
                echo "$test/".count($all_numero)."\n";
        }
		
		// suppose que c'est pour eviter de faire lancer la machine alors que l'on peut calculer bien plus facilement pour un seul nombre.
        if ($nb_max == 1){
                if (in_array($somme,$all_numero)){
                        return array(array($somme));
                        return true;
                } else {
                        return array();
                }
        }
		
		
        $r = false;
        $solution = array();
        foreach($all_numero as $numero){
		
		// on va parcourir tous nos chiffres 40 > 39 > 38 ..
		
                $trouve = trouve($all_numero,$somme-$numero,$nb_max-1) ; // j'avoue ne pas comprendre la subtilité de ce passage.. tu fais a chaque tout 150-40, 150-39, etc.. et 5-1, comprends rien ;-)
                
				
				foreach ($trouve as $i => $s){
                        $trouve[$i][] = $numero;
                        sort($trouve[$i]);
                        $solution[] = $trouve[$i];
                } 
        }
		
		// tu serialize pour avoir un string en comparaison je suppose, pas bete du tout.
        $solution = super_unique($solution);
        return $solution;       
}

// ici rien de compliqué..
$result = trouve($all_numero,$somme_a_trouver,$nb_element_max);

echo '<pre>';
print_r($result);
echo '</pre>'; 
Merci de ton aide et de ta patience.. je suppose que le secret dans la réalisation des algos, c'est.. pratiquer, pratiquer et pratiquer ?

Re: Modification d'un algo de calculs de somme

par epommate2 » 18 juin 2011, 08:11

me commenter le code afin d'y percer tous ces secrets ?
heuh... non, si tu ne comprend pas un truc, tu peux demander, mais je fais pas tout le travail !
D'ailleurs je ne vois plus d'array_sum, comment fait tu les additions ?
Tous est là :
$trouve = trouve($all_numero,$somme-$numero,$nb_max-1) ;

Re: Modification d'un algo de calculs de somme

par Nico » 17 juin 2011, 22:38

Ca marche comme un charme :-) <2Min pour obtenir le résultat, chapeau ;-)

Afin de conclure et te remercier une nouvelle fois, pourrez tu comme l'avait fait mon ami sur mon script original, me commenter le code afin d'y percer tous ces secrets ?

Merci bien.

ps : D'ailleurs je ne vois plus d'array_sum, comment fait tu les additions ? (car je faisais une alternative avec array_produit pour les multiplications :roll: )

Re: Modification d'un algo de calculs de somme

par Nico » 17 juin 2011, 09:10

Je teste dans la journée la version corrigé :-)

Pour ce qui est a quoi cela sert : je ne suis pas celui qui va utiliser directement le script.
De ce que j'ai compris, cela va servir a compléter un modèle mathématique en croisant plusieurs données. Le but final ? Aucune idée :-)

Re: Modification d'un algo de calculs de somme

par epommate2 » 17 juin 2011, 08:09

Pourquoi il y a un 4ème paramètre sur ta fonction alors que la fonction en compte que 3 ?
Une erreur de ma part :-)
500MO alloué est déjà pas mal, il essaie d'allouer .....24 octects ? truc qui cloche lol ?
Non, il a déjà alloué 500Mo et du coup, il essaye d'allouer un tout petit tableau de 24 octets supplémentaire et il n'y arrive pas ....

J'ai ca dans mon php.ini :
memory_limit = -1

Mais, je me suis apercu d'une petite erreur : array_unique ne fonctionne pas sur des tableaux grr...
$somme_a_trouver = 150;
$nb_element_max = 5;
$all_numero = array(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40);

function super_unique($array) {
  $result = array_map("unserialize", array_unique(array_map("serialize", $array)));
  return $result;
}

function trouve($all_numero,$somme,$nb_max){
	if ($nb_max == 4){
		static $test;
		$test++;
		echo "$test/".count($all_numero)."\n";
	}
	if ($nb_max == 1){
		if (in_array($somme,$all_numero)){
			return array(array($somme));
			return true;
		} else {
			return array();
		}
	}
	$r = false;
	$solution = array();
	foreach($all_numero as $numero){
		$trouve = trouve($all_numero,$somme-$numero,$nb_max-1) ;
		foreach ($trouve as $i => $s){
			$trouve[$i][] = $numero;
			sort($trouve[$i]);
			$solution[] = $trouve[$i];
		} 
	}
	$solution = super_unique($solution);
	return $solution;	
}


$result = trouve($all_numero,$somme_a_trouver,$nb_element_max);

print_r($result);
Par contre, j'ai une question... A quoi ca sert ?

Re: Modification d'un algo de calculs de somme

par Nico » 16 juin 2011, 19:52

Il y a en effet plus de 2000 resultats de mémoire.

J'ai testé ta dernière version mais j'ai 2 questions dont un problème.

Pourquoi il y a un 4ème paramètre sur ta fonction alors que la fonction en compte que 3 ?

Sinon je me prends un

Code : Tout sélectionner

Fatal error: Allowed memory size of 524288000 bytes exhausted (tried to allocate 24 bytes) in C:\... on line 25
500MO alloué est déjà pas mal, il essaie d'allouer .....24 octects ? truc qui cloche lol ?

Merci de tes réponses et ta volonté de m'aider ;-)

Re: Modification d'un algo de calculs de somme

par epommate2 » 16 juin 2011, 18:48

Re-tentative :

function trouve($all_numero,$somme,$nb_max){
	if ($nb_max ==4){
		static $test;
		$test++;
		echo "$test/".count($all_numero)."\n";
	}
	if ($nb_max == 1){
		if (in_array($somme,$all_numero)){
			return array(array($somme));
			return true;
		} else {
			return array();
		}
	}
	$r = false;
	$solution = array();
	foreach($all_numero as $numero){
		$trouve = trouve($all_numero,$somme-$numero,$nb_max-1) ;
		foreach ($trouve as $i => $s){
			$trouve[$i][] = $numero;
			$solution[] = $trouve[$i];
		} 
		
	}
	return $solution;	
}


$result = trouve($all_numero,150,5,1);
echo count($result)." résultat non trié";
foreach($result as $i => $r){
	sort($result[$i]);
}
array_unique($result);

print_r($result);
Mais j'ai l'impression qu'il y a BEAUCOUP de résultat ?

Re: Modification d'un algo de calculs de somme

par epommate2 » 16 juin 2011, 16:17

ok, je n'avais pas vu non plus les données du problème :-)

Re: Modification d'un algo de calculs de somme

par Nico » 16 juin 2011, 15:42

En mettant les mêmes paramètres, le script n'est toujours pas fini après 1H de lancement :oops:

chiffre: 150
nbre par : 5
1 a 40

Re: Modification d'un algo de calculs de somme

par epommate2 » 16 juin 2011, 14:36

Finalement, ca ne change pas grand chose :
<?php 

$debut=microtime(true);

$somme_a_trouver = 45;
$nb_element_max = 5;
$all_numero = array(1,2,8,7,3,-1,24, 44, 12,0,4,2,7,5,3,13,14,15,16,3);

array_unique($all_numero);

foreach($all_numero as $num){
	for($i=0; $i<$nb_element_max; $i++){
		$all_numero_final[] = $num;
	}
}

$all_combinaison  = array();

foreach($all_numero_final as $j => $numero){	
		foreach($all_combinaison as $i=> $list_element){			
			$all_combinaison[$i][] = $numero; 
			sort($all_combinaison[$i]);
			if (count($all_combinaison[$i]) == $nb_element_max){
				$sum = array_sum($all_combinaison[$i]);
				if ($sum == $somme_a_trouver){
					$solution[] = $all_combinaison[$i];
				}
				unset($all_combinaison[$i]);
			} else {
				if ( ! in_array($list_element,$all_combinaison)){
					$all_combinaison[] = $list_element;
				}
			}
		}
		
		$all_combinaison[] = array($numero);
	
	
}


print_r($solution);

echo microtime(true) - $debut;

Re: Modification d'un algo de calculs de somme

par Nico » 16 juin 2011, 14:10

Et la "grosse" difficulté est bien là :/