Rien de tel que de programmer sur une vraie bécane.
Même si je suis un grand fan du travail de
Remy et que j'utilise très souvent Pockemul pour programmer et tester des machine que je n'ai jamais pu toucher pour de vrai
En plus, j'aime bien le code de Céline.
D'abords parce que c'est un programme qui fonctionne et qui est très clair. Il pourra être adapté à toute sorte de machines.
Ensuite parce qu'il utilise l'instruction AREAD pour prendre la valeur à partir de l'affichage ou du dernier calcul fait sur la machine, ce qui en fait bien plus qu'un programme, c'est une véritable fonction utilisateur.
J'aime bien ce principe du code de l'utilisateur qui enrichit la bibliothèque de fonctions (ou programmes) de la calculette.
Par contre, je n'ai qu'un seul petit reproche, il n'est pas, dans cette première version parfaitement M.P.O.isé !
N'y aurait-il pas moyen de le modifier pour qu'il fasse et produise exactement les mêmes résultats mais en effectuant un peu moins d'opérations et surtout en prenant moins d'octets ou de lignes de code dans la mémoire du PC ?
Par exemple, je vois que les lignes 100 et 110 font partie d'un sous-programme. Celui-ci ne peut-il pas tenir sur une seule ligne (ce qui diminue l'emprise mémoire).
Je supprimerais donc la ligne 110 en collant le RETURN à la fin de la ligne 100 :
Malheureusement, ce sous-programme n'est appelé que par une seule partie du code (à la ligne 50). Est-ce nécessaire d'utiliser un sous-programme qui n'est pas partagé par plusieurs parties du code ? Nous ne sommes pas là en RPN ou il faut segmenter à cause des test/sauts limité à un seul pas.
Ne pourrait-on pas par exemple mettre le code du sous programme dans le programme directement ?
Mais je vois à l'instant que les lignes 50 et 60 commencent toutes les deux par le même test. Là aussi, on pourrait regrouper pour faire plus M.P.O.
aura le même effet que les deux lignes 50 et 60 sans la répétition du test (plus rapide à l'exécution et surtout plus court en mémoire
) Il me semble que Céline avait posé une question à ce sujet. Mais personne n’avait pris la peine de lui répondre !
Comme nous avons constaté que le sous-programme n'a pas de raison d'exister, on peut encore raccourcir :
Mais ne peut-on pas se débarrasser d'autre(s) ligne(s) inutile(s). Mais attention, sans pour autant supprimer des étapes ou des instructions.
Il est clair que les lignes où se fait un branchement ne doivent pas disparaitre, c'est à dire qu'il faut conserver la ligne 10 (à cause du label "S" entrée du programme), la ligne 40 (à cause du saut GOTO 40 de la ligne 50/60), la ligne 70 qui se trouve après un test (qui impose un saut de ligne quand il n'est pas satisfait) et la ligne 100 (si l'on avait conservé le sous-programme - mais je lui ai déjà réglé sons compte à celui-là).
Donc, d'après moi, les lignes 20, 30, 80 et 90 doivent pouvoir se caser ailleurs! C'est à dire dans les lignes "obligatoires".
Même souci d'économie pour les variables. Par exemple, la variable T est fort bien nommée. Il est clair que T signifie ici TEST. Elle n'est utilisée que pour cela d'ailleurs. Mais ce n'est peut-être pas nécessaire d'utiliser une variable juste pour mémoriser un résultat booléen. D'autant plus que j'ai déjà concaténé les deux lignes 50 et 60. Le TEST n'est donc plus effectué qu'une seule fois !
C'est la manie des M.P.O., il faut tout faire disparaitre, sous-programme univoque, variable temporaire à usage unique, ligne superflue, etc...
Bon, rassemblons les instructions sur les lignes "obligatoires", celles imposées par la logique des sauts et renvois de ligne :
Code : Tout sélectionner
10 : "S" AREAD N : E=1 : FOR X=2 TO √N
40 : D=N/X/X : IF D=INT D LET E=E*X : N=D : GOTO 40
70 : NEXT X : PRINT E;"√";N : END
Et pas mal. J'aime bien ce programme. Il est même bien plus court et bien plus MPO que le mien et presque aussi que celui de babaorhum mais avec l'énorme avantage qu'il fonctionne bien mieu
(cf. ex de 96 !)
Par conte, on peut copier l'idée de babaorhum et n'utiliser qu'une seule variable accumulatrice des facteurs quadratiques et on obtient bien alors le même code !
Mais quand même, c'est votre algorithme qui me posent problème.
Pour calculer √1073741824, vous avez réellement besoin de compter et tester tous les entiers entre 2 et 32768 ?
De ne tester que 2 et 3 n'est-ce pas suffisant ?
Une boucle FOR TO ... NEXT dont les bornes sont fixées est-elle bien appropriée ?
L’arrêt de la recherche des facteurs n’est-elle pas influencée par le nombre et la qualité des facteurs déjà trouvé ?
D'ou cette dernière proposition :
Code : Tout sélectionner
1:INPUT X : P=1 : R=X : I=2 : DO : IF R MOD I*I THEN I=NEXTPRIME(I) : ELSE P=P*I : R=R/I/I
2:LOOP UNTIL R<I*I : PRINT "√";X;"=";P;".√";R : END
Evidemment, il faut avoir une machine avec un BASIC MicroSoft. Je n'en connais pas qui tienne dans une poche !
A défaut, une calculette RPL :
Code : Tout sélectionner
4: 3: 2: 1:
x
« 1 2 x 1 2 @ Initialise P := 1 et i :=2 (avec r := x )
WHILE r p i
ROT p i r @ Positionne R dans la pile
OVER SQ p i r i² @ Calcule i²
DUP2 > @ Boucle Tant que R>i²
REPEAT
IF DUP2 MOD @ R et i² multiples ?
THEN @-> NON (R MOD i²<>0)
DROP ROT ROT r p i @ suprime i²
NEXTPRIME r p i' @ incrémente i (ou i devient nombre premier suivant :)
ELSE @-> OUI (R MOD i²==0)
/ p i r/i² @ R := R/i²
OVER 4 ROLL * i r/i² i*p @ P := P*i
ROT r' p' i
END
END
DROP SWAP DROP p r @ suprime valeur résiduelle de la pile
'a*√b' p r '~~~~'
4 ROT EXSUB
1 ROT EXSUB @ et formate le résultat sous forme d'une expression algébrique
»
'P*√R'
Bon, ce n’est qu’un premier jet. Je donne comme excercice de M.P.O.iser ce dernier code !
Les utilisateurs de HP28S devront fabriquer leur propre instruction NEXTPRIME (ou la remplacer par 1 + dans le code ci-dessus).