OVH Cloud OVH Cloud

fusion de deux nombres entiers...

16 réponses
Avatar
Jean-Francois Ortolo
Bonjour

Soient $n1 et $n2 deux nombres entiers, dont on sait que $n1 < $n2

Le problème, est de restituer la théorique bonne valeur de ces deux
nombres, sachant que s'ils sont différents, c'est que des chiffres
parasites se sont glissés dans l'un des deux nombres ( ou les deux ).

Je commence avec deux nombres, je continuerai avec plus que deux
nombres, car je dispose d'un certain nombre de nombres ( sic ) qui
devraient être égaux, mais le parasitage fait que, parfois, il ne le
sont pas.

Il est sûr que le parasitage ne consiste que dans l'ajout de chiffres
supplémentaires dans certains nombres, sans altération de l'ordre des
chiffres composant le nombre de départ ( non parasité ). Il n'y a jamais
de retrait de chiffres à cause du parasitage.

Donc, l'algorithme pour restituer le nombre réel, est évident: fusion
dans l'ordre de tous les nombres, pour ne retenir que les chiffres
appartenant à tous les nombres sans exception, tout en respectant
l'ordre. C'est donc un algorithme de fusion.

Pour se limiter à simplement deux nombres au départ, et sachant que
si $n1 == $n2, on retient $n1, on suppose donc, que $n1 < $n2.

Ma question est: Y a-t-il moyen d'opérer cete fusion, avec une
expression régulière ( Posix de préférence ), et une instruction de type
str_replace() ou, plus probablement: ereg_replace() ?

Comme $n1 < $n2, je pense que l'expression régulière pourrait être
déduite de $n1 ?

Merci beaucoup à vous pour vos réponses à ce problème, probablement
classique en PHP.

Bien à vous.

Amicalement.

Jean-François Ortolo


PS Je sais bien comment faire une fusion de deux chaînes de
caractères ( c'est cet algorithme-là que je veux implémenter ), mais je
cherche essentiellement à réduire le coût en durée d'exécution, donc à
utiliser une expression régulière et une instruction de remplacement, au
lieu de traiter chaque caractère ( chiffres ) les uns après les autres.

Les chiffres parasites peuvent être situés n'importe où dans les
nombres de départ.

--
Visitez mon site gratuit donnant des Statistiques
et des Historiques Graphiques sur les Courses de Chevaux:
http://www.ortolojf-courses.com

6 réponses

1 2
Avatar
Jean-Francois Ortolo
Etienne SOBOLE wrote:
Y a t-il une longeure maximale pour les chaine de chiffre???



Il n'y a pas de longueur maximale pour les chaînes de chiffres, on
suppose simplement, que comme les nombres non parasités doivent être
inférieurs à 28 ( 2 chiffres ), et que l'on suppose qu'un vingtaine de
chiffres parasites est bien un maximum, je pense que la chaîne de
chiffres, ne dépassera pas 20 chiffres.

Je serais interessé deja par voir l'algo po rapide que tu as mis au point,
car ce n'est pas trivial comme problèmatique..
Peut etre faut-il rechercher dans les algo de traitement du signal...

Ce qui est sur c'est que c'est pas ininteressant :)

Je vais chercher. A+
Etienne


Ben...

C'est un algorithme de fusion avec sélection de tous les chiffres
appartenant à la fois aux deux nombres, dans l'ordre rencontré.

Attention, c'est important de dire, que c'est dans l'ordre rencontré,
puisque le parasitage ne va pas changer l'ordre relatif des chiffres
initiaux, entre eux.

Donc, mettons $n1 et $n2, on accède à chaque chiffre avec un indice:

$n1[0] est le premier chiffre de $n1 et $n1[strlen("$n1") - 1] est
le dernier chiffre de $n1.

Voici un algorithme que j'ai concocté, merci de m'indiquer les
erreurs qu'il contient, ou des contre-exemples qu'il ne pourrait pas
traiter.



// $n3 ou $n4 doivent contenir le résultat.
$n3 = "";
$n4 = "";

$k = 0;
$l = 0;
$o = 0;
$p = 0;
if($n1 == $n2)
$n = $n1;
else {
while(true) {
$o = $k;
$p = $l;
$trouve1 = false;
for(; $k < strlen($n1); $k++) {
if($n1[$k] == $n2[$l]) {
$n3 .= $n1[$k];
$n4 .= $n2[$l];
$trouve1 = true;
break;
}
}

if(!$trouve1)
$k = $o;

$trouve2 = false;
for(; $l < strlen($n2); $l++) {
if($n2[$l] == $n1[$k]) {
$n4 .= $n2[$l];
$n3 .= $n1[$k];
$trouve2 = true;
break;
}
}

if(!$trouve2)
$l = $p;

if((!$trouve1)&&(!$trouve2))
break;

$k++;
$l++;

} // fin de la boucle while(true)

// résultat
// théoriquement $n3 et $n4 sont égaux.
if(strlen($n3) > 0)
$n = 0 + $n3;
else
$n = -1; // les nombres $n1 et $n2 sont incompatibles
}


Qu'est-ce que vous pensez de cet algorithmme ?

Le problème, serait de le faire tourner dans autant de nombres $n1 et
$n2 que possible, pour en détecter les erreurs, s'il en contient.

Merci beaucoup de votre aide.

Bien à vous.

Amicalement.

Jean-François Ortolo

--
Visitez mon site gratuit donnant des Statistiques
et des Historiques Graphiques sur les Courses de Chevaux:
http://www.ortolojf-courses.com

Avatar
Olivier Miakinen

Donc, mettons $n1 et $n2, on accède à chaque chiffre avec un indice:

$n1[0] est le premier chiffre de $n1 et $n1[strlen("$n1") - 1] est
le dernier chiffre de $n1.

Voici un algorithme que j'ai concocté, merci de m'indiquer les
erreurs qu'il contient, ou des contre-exemples qu'il ne pourrait pas
traiter.

[ snip algo ]

Qu'est-ce que vous pensez de cet algorithmme ?


Je ne recopie pas tout, mais voici quelques remarques. Tout d'abord, la
variable $n4 ne sert strictement à rien puisqu'elle ne peut en aucune
façon être différente de $n3. Par ailleurs, j'ai essayé de suivre à la
main l'algorithme avec un exemple donné dans la page¹ que t'a signalée
Michel Olagnon dans un autre groupe, où $n1 vaut "XMJYAUZ" et $n2 vaut
"MZJAWXU". En principe, le résultat devrait être "MJAU". Or :

1) Ton programme tel qu'il est semble retourner "MMZZ".

2) En rajoutant « $k++; $l++; » à chaque fois qu'un caractère est
trouvé, ça semble marcher avec ce jeu de tests ("MJAU"), mais...

3) En échangeant les rôles de $n1 et $n2, le résultat devrait toujours
être "MJAU" mais j'ai l'impression que ton code va retourner "XU".

Bref, pas terrible...

Le problème, serait de le faire tourner dans autant de nombres $n1 et
$n2 que possible, pour en détecter les erreurs, s'il en contient.


Essaye avec les chaînes données ci-dessus, dans un sens et dans l'autre,
quitte à remplacer les lettres par des chiffres si tu veux (mais ça ne
changera rien, bien sûr).


¹ http://en.wikipedia.org/wiki/Longest_common_subsequence_problem

Avatar
Etienne SOBOLE
¹ http://en.wikipedia.org/wiki/Longest_common_subsequence_problem


Ouai trop fort wikipedia...
bon d'accord c'est pile poil ce que JF recherchait, mais la piste de
Levenshtein etait bonne aussi :)

Bon ben voila. l'ffaire est classée.
Merci pour ce lien fort interessant.

a+
Etienne

Avatar
Jean-Francois Ortolo
Olivier Miakinen wrote: >

¹ http://en.wikipedia.org/wiki/Longest_common_subsequence_problem



Bonjour Monsieur

Je sais bien que mon algorithme ne marche pas, je l'ai dit dans un
message à part ( mon client de messagerie ne veut pas suivre les threads
quand je fais un forward ).

Donc, voici l'algorithme de wikipedia, non optimisé, en entier:

// $C[0..$m][0..$n] contient les distances.

// X[1..$m] contient les chiffres du 1er nombre, <=> $m = strlen($n1)
// Y[1..$n] contient les chiffres du 2ème nombre, <=> $n = strlen($n2)

// initialisation
// des variables
$C = array();
$X = array();
$Y = array();

$m = strlen($n1);
$n = strlen[$n2);
for($i = 1; $i <= $m; $i++)
$X[$i] = $n1[$i - 1];
for($j = 1; $j <= $n; $j++)
$Y[$j] = $n2[$j - 1];

// calcul des distances
for($i = 0; $i <= $m; $i++)
$C[$i][0] = 0;
for($j = 0; $j <= $n; $j++)
$C[0][$j] = 0;

for($i = 1; $i <= $m; $i++)
for($j = 1; $j <= $n; $j++)
if($X[$i] == $Y[$j])
$C[$i][$j] = $C[$i - 1][$j - 1] + 1;
else
$C[$i][$j] = max($C[$i][$j - 1], $C[$i - 1][$j]);

// En ce point, les valeurs
// $C[0..$m][0..$n] sont fixées.

// Fonction de lecture
// de la LCS ( longer common subsequence ),
// ou plus longue commune sous-séquence.
// Il faut appeler cette fonction
// avec les paramètres $i = $m et
// $j = $n.
// Cette fonction backTrack construit
// la chaîne LCS à rebourg,
// d'où le nom backTrack()

function backTrack($C, $X, $Y, $i, $j) {

if(($i == 0)||($j == 0))
return("");
else if($X[$i] == $Y[$j])
return(backTrack($C, $X, $Y, ($i - 1), ($j - 1)) . $X[$i]);
else {
if($C[$i][$j - 1] > $C[$i - 1][$j])
return(backTrack($C, $X, $Y, $i, ($j - 1));
else
return(backTrack($C, $X, $Y, ($i - 1), $j);
}
}


Et voilà.

J'espère que mon message, ne sera pas considéré par monsieur le
modérateur, comme relatif aux algorithmes plus qu'au PHP, mais comme
vous étiez intéressés par le dénouement de cette aventure... ;)

Merci beaucoup à Monsieur Miakinen de son aide.

Bien à vous.

Amicalement.

Jean-François Ortolo

--
Visitez mon site gratuit donnant des Statistiques
et des Historiques Graphiques sur les Courses de Chevaux:
http://www.ortolojf-courses.com

Avatar
Jean-Francois Ortolo
Bonjour

J'ai testé l'algorithme de wikipedia ci-dessus ( voir précédent
message ), il fonctionne très bien.

Le problème est résolu en ce qui me concerne, j'ai ainsi une boîte
noire pour calculer les numéros de chevaux corrects, à partir de
plusieurs numéros parasités ou non.

Merci beaucoup de votre aide, particulièrement Monsieur Miakinen,
dont j'ai suivi le lien vers wikipedia.

Bien à vous.

Amicalement.

Jean-François Ortolo

--
Visitez mon site gratuit donnant des Statistiques
et des Historiques Graphiques sur les Courses de Chevaux:
http://www.ortolojf-courses.com
Avatar
Olivier Miakinen

Merci beaucoup de votre aide, particulièrement Monsieur Miakinen,
dont j'ai suivi le lien vers wikipedia.


C'est trop d'honneur que tu me fais car, encore une fois, le premier à
donner ce lien était Michel Olagnon en réponse à ta question dans le
groupe fr.comp.algorithmes.

1 2