Non , il n'est pas mort.
C'est juste que tout le monde est plongé dans la lecture de la nouvelle Gazette !
Ton algorithme est très proche du mien.
La seule différence est que j ne "recherche pas" les H(v), H(u) ou H(w) à chaque pas, mais je fait avancer un pointeur qui donne tout de suite la bonne position pour le coup suivant.
Prenons le temps d'expliquer :
Dans un premier temps observons les dix premiers Nombre de Hamming :
Et voyons quels multiples de 2,3 et 5 ils peuvent chacun produire :
Code : Tout sélectionner
1 2 3 4 5 6 8 9 10 12
/|\ /|\ /|\ /|\ /|\ /|\ /|\ /|\ /|\ /|\
/ | \ / | \ / | \ / | \ / | \ / | \ / | \ / | \ / | \ / | \
2 3 5 4 6 10 6 9 15 8 12 20 10 15 25 12 18 30 16 24 40 18 27 45 20 30 50 24 36 60
Comme Pocket l’avait fait remarquer, chaque nombre de Hamming donne un nouveau nombre de Hamming et on peut construire la liste à partir d’un arbre.
Code : Tout sélectionner
1
┌──────────────────────────┼──────────────────────────┐
2 3 5
┌────────┼────────┐ ┌────────┼────────┐ ┌────────┼────────┐
4 6 10 6 9 15 10 15 25
┌──┼──┐ ┌──┼──┐ ┌──┼──┐ ┌──┼──┐ ┌──┼──┐ ┌──┼──┐ ┌──┼──┐ ┌──┼──┐ ┌──┼──┐
8 12 20 12 18 30 20 30 50 12 18 30 18 27 45 30 45 75 20 30 50 30 45 75 50 75 125
On constate que dans cet arbre, il y a beaucoup de feuilles communes et donc de branches identiques. En particulier celle issue des 5-multiples, mais aussi en partie des 3-multiples. Les branches issue des 2-multiple étant celles qui se répétent le moins.
Cette redondance va créer générer beaucoup de nombres redondants, ce qui va passablement ralentir le mécanisme de remise dans l’ordre de tout cela. Sans compter qu’il va falloir mémoriser de millier de nombre.
Il est possible de présenter l’arbre en l’organisant dans l’ordre des nombre :
Code : Tout sélectionner
1 =1
┌──────────────────────────┼──────────────────────────┐
2 │ │ =2
┌────────┼────────┐ 3 │ =3
4 │ │ ┌────────┼────────┐ │ =4
│ │ │ │ │ │ 5 =5
┌──┼──┐ 6 │ 6 │ │ ┌────────┼────────┐ =6
8 │ : ┌──┼──┐ │ ┌──┼──┐ │ │ │ │ │ =8
° │ : │ : : │ │ : : 9 │ │ │ │ =9
│ : │ : : 10 │ : : ┌──┼──┐ │ 10 │ │ =10
12 : 12 : : ┌──┼──┐ 12 : : : : : │ ┌──┼──┐ │ │ =12
° : ° : : : : : ° : : : : : 15 : : : 15 │ =15
: : : : : : : : : : : ┌──┼──┐ : : : ┌──┼──┐ │
: : : : : : : : : : : : : : : : : : : : │
° ° ° ° ° ° ° ° ° ° ° ° ° ° ° ° ° ° ° ° °
20 18 30 20 30 50 18 30 18 27 45 30 45 75 20 30 50 30 45 75 25
De cet arbre, il est possible d’éviter les redondances en se limitant uniquement à la première occurrence de chaque sous-branche, on obtient un arbre plus léger :
Code : Tout sélectionner
1 =1
┌──────────────────────────┼──────────────────────────┐
2 │ │ =2
┌────────┼────────┐ 3 │ =3
4 │ │ ┌────────┼────────┐ │ =4
│ │ │ │ │ │ 5 =5
┌──┼──┐ 6 │ ° │ │ ┌────────┼────────┐ =6
8 │ : ┌──┼──┐ │ │ │ │ │ │ =8
+ │ : │ : : │ 9 │ │ │ │ =9
│ : │ : : 10 ┌──┼──┐ │ ° │ │ =10
12 : ° : : ┌──┼──┐ : : : │ │ │ =12
+ : : : : : : : : : 15 ° │ =15
: : : : : : : : : ┌──┼──┐ │
: : : : : : : : : : : : │
° ° ° ° ° ° : : : : : : :
+ + 20 18 30 20 30 50 18 27 45 30 45 75 25
Cette dernière illustration montre comment l’arbre se développe. Les branches 2-multiples étant plus nombreuses mais formant des feuilles aux valeurs moins élevées que les sous-branches issues de 3 ou 5. Cette dernière étant les plus rares, mais produisant des nombres de Hamming plus élevés.
On constate aussi qu’à chaque pas, il faut sélectionner la feuille de valeur la plus faible (qui se trouve être le plus souvent celle issue des 2-multiples, mais pas toujours). Une fois la feuille minimale sélectionnée de valeur
h, cette sous-branche sera constituée des valeur 2h ,3h et 5h. Il y a de grandes chances que parmi ces trois racine, une ou deux sont communes avec une autre sous-branche car n’oublions pas que h est un nombre de Hamming.
Donc, tout revient comme s’il n’y avait , à chaque étape de la constituion de l’arbre que trois bourgeons possibles, l’un 2-multiple, l’autre 3-multiple et le dernier 5-multiple.
D’où l’idée de construire l’arbre à partir de trois pointeurs :
Comme pour le code de
gégé, d’utiliser les 3 pointeurs que l’on déplace sur la liste des nombres de Hamming que l’on a déjà construite.
Au départ, on n’a que la racine 1 dans cette liste : les trois pointeurs
a,
b et
c pointent donc tous sur cet unique élément, générant les prochains candidats
a 3 et
5 (respectivement
2*H(a), 3*H(b) et 5*H(c).
Comme l’on veut générer la liste des nombres de Hamming dans l’ordre, je prends le plus petit de ces trois candidats qui est
2 généré par le pointeur
^a. C'est-à-dire celui qui génère les 2-multiples. Ma liste est alors
{ 1 2 }. Elle contient tous les 2-multiples obtenus du début jusqu’à la position
^a ; je fais donc avancer d’un pas le pointeur
^a.
Les candidats suivants sont alors
4,
3 et
5. Je prends bien évidemment le plus petit qui est en fait issu du pointeur
^b générant les 3-multiples.
C’est à nouveau le candidat proposé par le pointeur
^a qui est minimum. Et oui, rappelons nous, les branches redondantes issues des 2-multiples sont les plus nombreuses. Le pointeur
^a est donc celui qui avance le plus souvent. C’est aussi celui qui avance le moins vite, car on ne multiple la valeur pointée que par 2 au lieu de 3 ou de 5 pour les autres pointeurs.
Pour une fois, c’est le pointeur
^c qui donne le candidat suivant le plus petit.
Le plus petit candidat est alors 6 proposé par
^a
Puis
8 toujours proposé par
^a. On constate que cette fois les trois pointeurs sont distincts et dans l’ordre
^c ^b ^a qui correspond bien à celui du déplacement le plus lent (car vitesse 5x ) ou plus rapide (vitesse 2x seulement).
On constatera que les pointeurs
^c et
^a proposent le même candidat
10 qui est multiple de 2 et 5.
Cependant, le plus petit des candidats est
9 donné par
^b
Ici, le candidat minimum est
10, il est donné par
^c et
^a, il faut donc faire avancer ces deux pointeurs car tous les 5-multiples ont été proposés pour 1 et 2 ainsi que tous les 2-multiples pour 1,2,3,4 et 5.
Et le dernier élément est
12 donné par
^b et
^a :
Et ainsi de suite …
Voilà cela donne un code dont le principe est le même que celui proposé par
gégé, à ceci prêt que l’on n’a pas à rechercher les H(u), H(v) ou H(w), car leur « position » est mise à jour « automatiquement » à chaque pas.
Code : Tout sélectionner
LIST
10 m%=511: DIM H(m%): N=1: A=2:B=3:C=5: INPUT r% : T0=TIMER
20 DO
30 : h%=n% AND m%: n%=n%+1: H(h%)=N: IF r%<92 THEN PRINT N,
40 : IF A=N THEN a%=(a%+1)AND m%: A=2*H(a%)
50 : IF B=N THEN b%=(b%+1)AND m%: B=3*H(b%)
60 : IF C=N THEN c%=(c%+1)AND m%: C=5*H(c%)
70 : N=MIN(A,B,C)
80 LOOP WHILE n%<r%
90 PRINT N:PRINT "H(";n%;"=";H(h%);tab(30);INT((TIMER-T0)/6)/10;"s"
ready.
run
? 10
1 2 3 4 5 6 8 9
10 12 15
h 10 = 12 .4s
ready.
run
? 50
1 2 3 4 5 6 8 9
10 12 15 16 18 20 24 25
27 30 32 36 40 45 48 50
54 60 64 72 75 80 81 90
96 100 108 120 125 128 135 144
150 160 162 180 192 200 216 225
240 243 250
h 50 = 243 2.3s
ready.
RUN
? 100
h 100 = 1536 3.8s
ready.
RUN
? 200
h 200 = 16200 7.9s
ready.
_
La variable m% et les AND m% permettent d’utiliser de façon circulaire la mémoire du tableau DIM H(m%) et donc de déterminer plus de valeur dans un espace mémoire réduit.
En effet, rien ne sert de garder en mémoire les valeur H() inférieur à la position du pointeur
^c (c'est-à-dire la variable c%)
Bon, mais cela ne revient qu’à utiliser un algorithme basé sur le fait que si H est un ensemble de nombres de Haming, alors 2.H, 3.H et 5.H le sont également et que donc on peut construire un arbre qui parcouru astucieusement donne la suite des nombres dans l’ordre.
Il doit exister d’autres moyens à partir d’autres approche.
Comme par exemeple les puissances [p q r] successives [2 3 5] ou l’approche géométique des tétrades des point (x,y,z) dans le repère géométrique (*2 *3 *5) .
Code : Tout sélectionner
H [ p q r ] H [ p q r ] H [ p q r ]
--- ---------- --- ---------- --- ----------
1 0 0 0 15 0 1 1 40 3 0 1
2 1 0 0 16 4 0 0 45 0 2 1
3 0 1 0 18 1 2 0 48 4 1 0
4 2 0 0 20 2 0 1 50 1 0 2
5 0 0 1 24 3 1 0 54 1 3 0
6 1 1 0 25 0 0 2 60 2 1 1
8 3 0 0 27 0 3 0 64 6 0 0
9 0 2 0 30 1 1 1 72 3 2 0
10 1 0 1 32 5 1 0 75 0 1 2
12 2 1 0 36 2 2 0 80 4 0 1
Ainsi que la méthode 3D-géométrique :
