Bonjour,
Je me suis mis en congé de mes programmations en OPL pour passer la semaine dernière sur la résolution automatique du problème sur HP-34c,
ma caltoche de la semaine.
J'ai préféré utiliser mon algorithme :
1. Décaler le 1 d'une tour à gauche ;
2. Décaler la plus petite décimale suivante :
2a. d'une tour à gauche si elle est impaire ;
2b. de deux tours à gauche si elle est paire ;
3. Recommencer en 1.
On pourrait très bien décaler alternativement à droite et à gauche, mais mon programme fonctionne avec énormément de sous-programmes et j'ai opté pour deux décalages à gauche... soit le même sous-programme répété.
J'ai essayé de trouver une régularité dans le choix de la tour initiale pour chaque déplacement, mais en vain... il y en a certainement une, mais sur une trop longue période pour qu'elle soit intéressante à algorithmiser
(oui, je néologise, et alors ? c'est toujours mieux que de parler globish !).
J'éditerai pour quelques commentaires additionnels, mais voici déjà le programme (à optimiser, notamment dans la partie test) :
Code : Tout sélectionner
001 LBL A // "A" pour Automatique, le mode DEMO.
002 CL. Reg. // Efface les registres.
003 8
004 1
005 1/x
006 STO-1
007 1
008 0
009 STO+1 // R1=9,987654321 (l'entier correspond au nombre de décimales)
010 1
011 STO I
012 GSB 0 // La routine 0 affiche R1, R2 ou R3 avec l'entier correspondant au numéro de registre (ou tour).
013 GSB 1 // La routine 1 décale la tour de référence d'un vers la gauche, avec saut à 3 si nécessaire.
014 LBL 8 // Début de la grande boucle : recherche de la décimale 1 (le disque le plus petit).
015 GSB 5 // La routine 5 extrait la dernière décimale de la tour de référence.
016 .
017 1
018 x=y? // Comparaison. Si 1 (le plus petit disque) a été trouvé, on sort de la boucle.
019 GTO 9 // Saute quelques pas ; l'étiquette LBL 9 revient souvent, permettant ainsi ce que j'appelle le saute-mouton.
020 GSB 1 // Décalage.
021 GTO 8 // Si le pgm n'a pas trouvé 1, on recommence.
022 LBL 9
023 Rd // Roll Down (décale la pile d'un niveau vers le bas).
024 GSB 6 // La routine 6 exécute la décapitation de la tour et montre sa tête au peuple ("elle en vaut la peine !")
025 GSB 1 // Décalage (toujours d'une seule tour pour 1).
026 GSB 2 // La routine 2 assure la réception de la décimale sur la tour d'accueil.
027 GSB 0 // Visualisation du nouvel emplacement.
028 RCL 3 // Le registre (la tour) 3 est rappelé(e) pour savoir si le jeu est fini.
029 9
030 x<=y?
031 GTO 4 // La routine 4 affichera le score.
032 GSB 1 // On cherche à présent la deuxième décimale la plus petite.
033 GSB 5 // Extraction de décimale...
034 RCL 0 // La partie décimale va mémoriser la première décimale trouvée.
035 INT
036 +
037 STO 0
038 GSB 1 // Décalage...
039 GSB 5 // Extraction de la deuxième décimale (il ne peut y avoir que 2 tours concernées, la dernière est occupée par le 1).
040 RCL 0 // Comparaison avec la première...
041 FRAC
042 x=0? // ... mais si la tour est vide, il n'y a plus de comparaison !
043 GTO 9
044 x>y?
045 GTO 9 // Comparaison de la 1ère et la 2ème. Si la deuxième est plus petite, c'est la bonne (comme lors du test à 0 précédent).
046 x<->y // Sinon, on positionne correctement la 1ère décimale pour qu'elle soit remise en x en LBL 9 (on doit pouvoir améliorer ça).
047 GSB 1
048 GSB 1 // Double décalage, car on se réfère alors à la tour de droite.
049 LBL 9
050 x<->y
051 X#0? // Si la deuxième décimale extraite est égale à 0, on veut l'autre !
052 GTO 9 // Référence à une étiquette à venir plus bas...
053 x<->y
054 GSB 1
055 GSB 1 // Double décalage.
056 LBL 9
057 GSB 5 // Extraction réelle de la décimale.
058 GSB 6 // Affichage de la tour décapitée et la tête d'icelle.
059 RCL 0
060 INT
061 +
062 STO 0 // Stockage de la décimale pour usage ultérieur.
063 FRAC // Test de parité.
064 5
065 * // Eh oui : multiplier par 5 équivaut à multiplier par 10 et diviser par 2 pour savoir si la décimale est paire ou non.
066 FRAC
067 x=0?
068 GSB 1
069 GSB 1 // Si la décimale est paire, en effet, il faut décaler 2 fois à gauche ; si elle est impaire, une seule fois.
070 RCL 0
071 FRAC // Récupération de la décimale (perdue au-delà de la pile si on ne procède pas à cette occupation de registre)
072 GSB 2 // Positionnement de la décimale sur la nouvelle tour.
073 GSB 0 // Visualisation de la tour.
074 GTO 8 // Fin de la grande boucle, on repart à la recherche du 1.
075 LBL 6 // Décapitation de la tour initiale.
076 -
077 x<->y
078 /
079 1
080 -
081 STO (i)
082 GSB 0 // Visualisation.
083 Ru // Roll Up : Rotation de la pile vers le haut.
084 1
085 x<->I // Procédure nécessaire pour visualiser la seule décimale nécessaire (voir aussi LBL 0).
086 DSP I
087 x<->y
088 PSE // Affichage de la décimale.
089 x<->y
090 x<->I // On rétablit le registre I comme il était auparavant.
091 1
092 STO+0 // Comptage du nombre de coups.
093 Rd
094 Rd
095 RTN // Fin de la routine de décapitation.
096 LBL 5 // Routine d'extraction de la décimale.
097 RCL (i)
098 ENTER
099 INT
100 1
101 -
102 10^x
103 *
104 Lst X
105 x<->y
106 FRAC
107 Lst X
108 x<->y
109 RTN // Fin de la routine d'extraction.
110 LBL 4 // Routine de fin avec affichage du score.
111 RCL 0
112 FIX 0
113 RTN // Fin de la routine de fin.
114 LBL 2 // Routine de réception de décimale sur la nouvelle tour.
115 1
116 STO+(i) // Augmentation du nombre de décimales noté dans la partie entière.
117 Rd
118 RCL (i)
119 INT
120 1
121 -
122 10^x
123 ENTER
124 Rd
125 /
126 x<->y
127 Rd
128 +
129 x<->y
130 /
131 STO (i)
132 RTN // Fin de la routine de réception de décimale.
133 LBL 1 // Routine de décalage de la tour de référence.
134 DSE // Le test "Decremente & Skip if Equal (to zero)" est préférable à "Incremente and skip if greater" parce qu'il évite de remplir la condition du test en I.
135 GTO 9
136 3
137 STO I // Si I=0, alors I=3.
138 Rd
139 LBL 9
140 RTN // Fin de la routine de décalage.
141 LBL 0 // Routine de visualisation de tour (il faut indiquer le numéro de registre dans la partie entière).
142 RCL I
143 RCL (i)
144 FRAC
145 +
146 RCL (i) // Il faut aussi n'afficher que les décimales nécessaires.
147 INT
148 x<->I
149 Rd
150 DSP I
151 PSE
152 Ru
153 x<->I
154 RTN // Fin de la routine de visualisation de tour.
VARIABLES :
Registre I : Numéro de tour (1, 2 ou 3) OU Nombre de décimales à afficher (1 à 9).
Registre 0 : Nombre de coups joués en partie entière ; décimale autre que 1 en partie décimale.
Registres 1, 2 et 3 : Tours 1, 2 et 3 avec le nombre de décimales de chacune en partie entière.
4*7+154=182 octets.
Notez que le temps d'exécution est très long :
près de 3 heures ! beaucoup plus lente qu'un être humain, mais au moins, la 34c ne se plante pas...

Je comptais réaliser une petite vidéo, mais là, 3 heures...
À la décharge de la machine, signalons que les pauses (visualisation de la tour de départ, de la décimale retirée, de la tour d'arrivée), à raison d'une seconde d'arrêt (environ), coûtent (3*511) 1 533 secondes, soit 25 minutes et 33 secondes - mais il faut bien montrer les déplacements, n'est-ce pas ?
Il reste 18 pas pour ajouter la version B (Mode Joueur ou Manuel) actionnée par la touche
de la 34c ("B" pour : Bon ben y'a plus qu'à !).
Ce sera pour un autre épisode !
(1ère édition : correction de deux erreurs de syntaxe et d'une d'orthographe)