Autorisation : Membre
Nb de messages : 4
Inscrit le : Mar 05 Aoû 2014, 22:28
Posté le : Mar 05 Aoû 2014, 22:45
Bonsoir à vous,
Alors voilà je suis en ce moment sur un programme assez basique sur TI-82 stats.fr pour lequel votre aide me serait précieuse. Il s'agit du 2048 ! Au moment où la calculette est censé choisir une des cases de la grille pour afficher de manière aléatoire un chiffre (2 ou 4). Et bien jusqu'à présent, dans cette situation, je programmais cela : (le 'L' est le petit L des listes et =/= est le signe non égal à)
Lbl G
entAléat(1,16)->A
If 'L'MU(A)=/=0 /// Sachant que les valeurs des 16 cases sont stockées dans la liste 'L'MU
Then
Goto G
End
Je suis conscient q'il s'agit de la méthode la plus intuitive (d'après moi, qui suis novice). C'est un problème lorsque 14 cases (par exemple) sont déjà prises par des valeurs, parce qu'à ce moment là, la calculette peut mettre très longtemps à tomber sur les deux seules cases libres de la grille à coup de tirage aléatoire
Il s'agit donc d'optimisation de programme, car sinon il est fonctionnel (mais long !).
Pardonnez-moi si ce sujet a déjà été traité (en tout cas je ne l'ai trouvé nul part...) et merci pour vos éventuelles réponses ! ^^
Autorisation : Membre
Nb de messages : 3738
Inscrit le : Lun 19 Oct 2009, 21:25
Posté le : Mer 06 Aoû 2014, 0:56
La lenteur vient principalement de ton codage, pas tant de l'algorithme. En effet le Goto cause des problèmes de ralentissements lorsqu'il est mal utilisé.
La première chose à corriger est le Then/End inutile qui cumule des ralentissements. J'en profite pour optimiser la condition : tout nombre non nul est vrai donc "=/=0" est facultatif.
Code
Lbl G
entAléat(1,16->A
If 'L'MU(A
Goto G
Voici le grand classique, l'essentiel est le choix du Repeat plutôt que While/For/Goto.
Code
Repeat not('L'MU(A
entAléat(1,16->A
End
J'utilise Repeat pour ne pas avoir besoin de doubler le code d'affection de A (While l'aurait nécessité avant) et not() pour détecter la valeur nulle efficacement.
Utiliser un tableau, donc une matrice, au lieu d'une liste sera bien plus intuitif pour coder les déplacements. Je préfère cela quitte à avoir une paire d'aléatoires (paire de coordonnées) plutôt qu'un seul aléatoire.
Maintenant traitons d'autres algorithmes.
Pour retrouver les cases libres immédiatement comme tu espères, je voie deux possibilités :
-utiliser un inventaire des cases libres
-parcourir les données jusqu'à trouver une case libre
Ces deux méthodes demandent plus de traitement ou plus de mémoire. Je ne pense pas que compliquer l'algorithme soit utile pour seulement 16 cases et la fonction pseudoaléatoire de la TI.
Et dans le cas d'un jeu tel que 2048 ou les données sont déplacées, je juge délirant d'utiliser la méthode de l'inventaire. edit: je déconseillais l'inventaire à cause du besoin de mettre à jour l'inventaire au moment du déplacement.
Je choisis une case puis parcourt jusqu'à en trouver une autre libre. Cela peut prendre plus de temps dans certains cas particuliers que de répéter l'aléa, mais cela ne dépassera jamais la durée du parcourt de chaque case contrairement à une répétition d'aléatoires en théorie.
Code
entAléat(1,16->A
While 'L'MU(A
A+1-16(A=16->A
End
J'utilise While pour tester la case avant de parcourir et aussi pour me passer de not().
A+1-16(A=16) utilise simplement le résultat booléen de la condition (A=16) qui donne 0 ou 1. Ainsi on incrémente, et reprend à 1 si on dépasse 16.
---------------------- ti82statfr: 2008, inscrit: 2009, ti84pocketfr: noël2011, ti30xbmultiview: iut 2012-2014
Perfectionniste, manque tact. Pas le temps de tout publier depuis 2011. Répond toujours aux questions. (rédigé juin 2014)
Ah oui... Je n'y aurait pas pensé tout seul merci !
A la limite, je viens d'avoir une autre idée, peut-être pas aussi performante que la tienne, qui consiste à vraiment choisir une valeur aléatoire parmi les 16 cases de départ. Puis si la case trouvée n'est pas égale à zéro, on remplace cette valeur par la dernière de la liste, et le prochain tirage aléatoire se fera avec 15 cases possibles seulement... Et ainsi de suite. Ce qui permet d'être sûr que la calculette ne fera pas plus de 16 tirage aléatoire pour trouver . Voilà le code :
{4,2,4,4,8,4,4,0,2,4,16,2,4,8,2,2}->'L'6 ///Je doute que cette répartition dans les cases soit possible... Mais les valeurs sont prises au hasard ici...
0->C : 16->E
Lbl A
entAléat(1,E)->A
If L6(A) /// apparemment le ''=/= 0'' est inutile
L6(E)->L6(A) /// et le ''then'' et ''end'' également...
E-1->E
C+1->C
Goto A
Désolé de ne pas avoir optimisé au maximum avec ce que tu m'as conseillé linkakro, mais je ne suis pas sûr de savoir utiliser le repeat not pour le moment, et je n'ai pas trop le temps immédiatement... Je reverrai cela ce soir.
Est-ce que tu pourrais tout de même me dire ce que tu en penses de ce nouveau code ?
Autorisation : Membre
Nb de messages : 4
Inscrit le : Mar 05 Aoû 2014, 22:28
Posté le : Mer 06 Aoû 2014, 9:23
Par contre le problème est que la liste utilisée (ici L6) ne pourra pas être la même que celle que l'on utilise tout le long pour opérer des déplacements des cases par exemple. Il faudra simplement assimiler cette dernière dans L6 après chaque demande de déplacement (pression droite...).
Je ne sais pas si j'ai été clair
Autorisation : Membre
Nb de messages : 3738
Inscrit le : Lun 19 Oct 2009, 21:25
Posté le : Mer 06 Aoû 2014, 13:52
Ne t'inquiète pas à propos des optimisations. Je n'attends pas que tu maîtrises immédiatement quatre types d'optimisation.
Repeat = répète jusqu'à ce que la condition soit vraie (non nulle). Donc poursuit tant que la condition est fausse.
While = commence la boucle si la condition est vraie, et demeure dedans tant qu'elle est vraie. (donc quitte si conditions fausse/nulle)
non(condition) = intervertit vrai et faux.
Donc While et Repeat sont similaires, et on peut adapter une condition simplement en ajoutant non().
Les Then/End sont facultatifs lorsqu'une seule action est présente dans l'alternative du If. Un Goto isolé dans un If:Goto ne pose pas les problèmes de If:Then:Goto:End.
Ce que tu proposes convient, l'optimisation est adéquate, mais je ne comprend pas le but de l'algorithme.
Citer : lebatteurfou
consiste à vraiment choisir une valeur aléatoire parmi les 16 cases de départ. Puis si la case trouvée n'est pas égale à zéro, on remplace cette valeur par la dernière de la liste, et le prochain tirage aléatoire se fera avec 15 cases possibles seulement... Et ainsi de suite. Ce qui permet d'être sûr que la calculette ne fera pas plus de 16 tirage aléatoire pour trouver
Citer : lebatteurfou
Par contre le problème est que la liste utilisée (ici L6) ne pourra pas être la même que celle que l'on utilise tout le long pour opérer des déplacements des cases par exemple. Il faudra simplement assimiler cette dernière dans L6 après chaque demande de déplacement
Je pense ne pas comprendre ce que tu veux faire. J'interprète des choses contradictoires.
La liste L6 contient-elle des valeurs ou des coordonnées des valeurs dans la grille LMU ?
Je pense que tu veux y stocker des données, alors que j'y stockerais plutôt des coordonnées.
-Si ce sont des coordonnées alors je crois que tu penses à ce que j'ai surnommé "l'inventaire des cases libres" et que j'ai déconseillé à cause du traitement des déplacements qui doit alors se répercuter sur l'inventaire.
-Si ce ne sont pas des coordonnées alors je pense que tu fais fausse route puisque posséder la valeur ne donne aucune information sur son emplacement.
Éclaircis tout cela je te prie, avant que je commence à coder des exemples.
---------------------- ti82statfr: 2008, inscrit: 2009, ti84pocketfr: noël2011, ti30xbmultiview: iut 2012-2014
Perfectionniste, manque tact. Pas le temps de tout publier depuis 2011. Répond toujours aux questions. (rédigé juin 2014)
Autorisation : Membre
Nb de messages : 4
Inscrit le : Mar 05 Aoû 2014, 22:28
Posté le : Mer 06 Aoû 2014, 20:43
Alors en fait, le numéro tiré entre 1 et 16 n'est que le numéro de la case, qui est ensuite traduit en coordonnées... Etant donné que je débute vraiment en programmation, j'ai du mal à expliquer ma démarche. Donc je vais recopier mon code du jeu 2048 en essayant qu'il soit facilement compréhensible :
Code
0 -> 0 : 0 -> Z /// Z est le score
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} -> LMU /// J'utilise cette liste pour stocker les valeurs des cases de 1 à 16
EffDessin
0->Xmin : 94->Xmax
0->Ymin : 62->Ymax
3->X
While X =/= 113
Ligne(X,56,X,1
X+22->X
End
56->Y
While Y =/= -14
Ligne(3,Y,91,Y
Y-14->Y
End
/// Jusque là je n'ai fait que tracer la grille
46->G : 10->D
Lbl A
If Z/D>=1 /// Cette boucle permet que le score soit centré sur l'écran quelque soit sa longueur (EDIT : pardon, c'était une erreur de ma part, ce n'est pas Z/D=/=1)
Then
G-2->G : 10D->D
End
Texte(0,G,Z
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} -> LNU /// Cette liste est compliquée à expliquer... En fait, si la case 6 (par exemple) a déjà été additionnée à une autre case pendant ce ''tour'', 1->LNU(6) ce qui permet que cette case ne se ré-adittionne pas à une autre case pendant ce tour
Lbl G
Entaléat (1,16)->A
If LMU(A) =/= 0 : Then /// Le fameux passage dont il est question (pas forcément celui qui a le plus besoin d'être optimisé d'ailleurs)
Goto G : End
Entaléat (1,40)->B
If B=1 : Then
4->C : else : 2->C : End /// Ce qui permet d'avoir 1 chance sur 40 que le numéro qui s'affiche aléatoirement dans la grille soit un 4
parEnt(A/4.1)+1->Y
A-parEnt(A/4.1)*4->X /// une sorte de fonction modulo permettant de donner la colonne (X) ainsi que la ligne (Y) correspondant à la case (ses coordonnées)
C->LMU(A)
LMU->LOU /// LOU sera la liste LMU AVANT toute modification, utile pour la suite
Z+C->Z /// La case ajoutée s'additionne au score
Texte(-4+14Y,-15+22X,C /// La valeur tirée aléatoirement s'affiche sur l'écran
0->K
While K =/= 24 et K =/= 25 et K =/= 26 et K =/= 34
codeTouche->K
End
If K=24
Then
1->I : 1->P : 4->S
End
If K=25
Then
1->I : 4->P : 1->S
End
If K=26
Then
4->I : -1->P : 4->S
End
If K=34
Then
13->I : -4->P : 1->S
End
0->H /// Et c'est là que ça va peut-être se compliqué...
While H<4
I->J
J+P->Q : 1->W : 1->R
If LMU(Q)=LMU(J)=LMU(J-P)=LMU(J-2P) et LMU(Q)=0
Then
4->W /// Permet de ne pas faire de changement sur la grille si les 4 cases d'une même ligné sont nulles... C'est une perte de temps d'additionner deux cases valant 0 parce qu'elles ont la même valeur... Mais apparemment cette partie fait buger le programme
End
While W =/= 4 /// Je vais essayer d'expliquer cette partie en dessous du code
While R>0
If LMU(Q) =/= 0
Then
If LMU(Q)=LMU(J) et LNU(Q)=0 et LNU(J)=0
Then
LMU(Q)*2->LMU(J)
1->LNU(J)
0->LMU(Q)
Z+LMU(J)->Z
End
If LMU(J)=0
Then
LMU(Q)->LMU(J)
0->LMU(Q)
End
End
R-1->R
Q-P->Q : J-P->J
End
W+1->W
Q+WP->Q : J+WP->J
W->R
End
H+1->H : I+S->I
End
1->F
While F<17
If LMU(F) =/= LOU(F)
Then
partEnt(F/4.1)+1->Y
F-partEnt(F/4.1)*4->X
If LMU(F) =/= 0
Then
Texte(-4+14Y,-15+22X,LMU(F)
End
If LMU(F)=0
Then
Texte(-4+14Y,-15+22X,’’ ‘’
End
End
F+1->F
End
Goto A
EDIT par linkakro : balise code, indentation et lignes espaces ajoutées.
Alors ce qui fait que mon programme est long, c'est ma manière de procéder. En fonction de la touche pressée, je stocke des valeurs dans trois variables : I,P et S. Quelque soit la flèche pressée, la procédure est la même. Donc je vais simuler une pression de la flèche du bas.
I=13 : c'est la case à partir de laquelle on va faire nos recherches. On va la comparer à la case 9 (d'où P=-4) pour savoir si les deux s'additionne ou non.
Une fois que c'est fait, on analyse si la case 9 et la 5 sont pareil, et on ré-analyse les cases 9 et 13 (à chaque fois on ''repart'' d'un case au-dessus en redescendant). Puis une fois que toutes les cases de cette colonne (qui peut être une ligne si la touche pressée est celle de droite ou de gauche) on procède de même en se décalant d'une colonne (d'où S=1).
Je trouve que cette partie est très difficile à expliquer à l'écrit, donc j'espère que j'ai été clair (même si je ne pense pas )
Et pour revenir à mon LNU, si deux cases veulent s'additionner, mais que l'une d'entre elle vaut 1 dans la lite LNU, alors elles ne s'additionneront pas parce que cela signifie que celle-ci l'a déjà fait.
Donc ce code est pour le moment sans les propositions d'optimisations vu plus tôt dans ce sujet.
Autorisation : Membre
Nb de messages : 3738
Inscrit le : Lun 19 Oct 2009, 21:25
Posté le : Jeu 07 Aoû 2014, 0:37
Utilise la balise code. Et aère en séparant les parties. Indenter le code permet de repérer les blocs d'algorithmie.
J'édite moi-même la balise (modérateur powa), mais tu connais les zones mieux que moi. Tu peux éditer toi-même ton message car tu étais déjà inscris.
J'abuse des balises codes en y mettant du texte si cela permet de séparer des propos, mais je doute que cela plaise à tout le monde.
En programmation la bonne habitude est de toujours utiliser des conditions de comparaison d'ordre et non d'égalité. Sinon le jour où quelque chose est mal initialisé, les conditions d'égalité ne conviennent pas.
(Je connais même une implémentation du langage vérilog qui ne permet pas d'initialiser, donc tout doit être prévu.)
Par pitié utilise des boucles For au lieu des While et Repeat quand tu n'as aucune condition annexe, car cela est bien plus concis.
3->X
While X =/= 113
Ligne(X,56,X,1
X+22->X : End
56->Y
While Y =/= -14
Ligne(3,Y,91,Y
Y-14->Y : End
///////////////////
3->X
While X >= 110
Ligne(X,56,X,1
X+22->X : End
56->Y
While Y >= 0
Ligne(3,Y,91,Y
Y-14->Y : End
///////////////////
For(X,3,110,22
Ligne(X,56,X,1
End
For(Y,56,0,-14 // 0,56,14 fera l'affaire dans l'autre sens
Ligne(3,Y,91,Y
End
Code
If Z/D=/=1
///////////////////
If Z=/=D
///////////////////
If Z-D
Code
C'est quoi ce 4.1 ???
parEnt(A/4.1)+1->Y
A-parEnt(A/4.1)*4->X
Ce 4.1 doit servir à changer une phase du cycle modulo ou une frontière. C'est aberrant à mon avis, car cela ne fonctionne qu'aux conditions d'avoir A un nombre décimal et suffisamment grand devant 0.1.
Tu peux tenir à utiliser cela, mais je ne le conseille pas.
Et puis j'ai pour obsession de ne calculer qu'une seule fois la division si je peux. Cela est juste personnel.
1+ent((A-1)/4->Y
A-4Y-4->X
Code
entAléat(1,40)->B
If B=1
///////////////////
If 1=entAléat(1,40
///////////////////
If not(entAléat(0,39
Code
0->K
While K =/= 24 et K =/= 25 et K =/= 26 et K =/= 34
///////////////////
Repeat K=24 or K=25 or K=26 or K=34
///////////////////
dès ti82stats on peut même optimiser comme ça.
Repeat max(K={24,25,26,34
Code
If LMU(Q)=LMU(J)=LMU(J-P)=LMU(J-2P) et LMU(Q)=0
Then
4->W
End
///////////////////
Élimine le Then End puisque tu as une seule commande.
Et écris des conditions que les machines peuvent gérer, c'est-à-dire une seule comparaison à la fois puis des opérateurs booléens tels que "et".
If LMU(Q)=LMU(J) et LMU(Q)=LMU(J-P) et LMU(Q)=LMU(J-2P) et LMU(Q)=0
4->W
Ce que tu appelles "faire bugguer le programme" n'est pas clair du tout. Un bug est un défaut de comportement. Or d'après la syntaxe fausse de la condition au dessus, tu as forcément obtenu un plantage et le message d'erreur de syntaxe qui doit signaler l'emplacement de l'erreur dans la condition. Me dire que cela plante, et me dire que c'est dans la condition, aurait été d'une aide précieuse. EDIT : Pardon j'ai eu tort d'affirmer ce dernier paragraphe. Toutes mes excuses pour ce excès de confiance. La condition est mal écrite pour ce qu'on en veut mais ne cause aucun message d'erreur de syntaxe. Détails dans la suite du sujet...
Je reviendrai à la charge plus tard pour savoir ce que tu as en tête avec le code du Mer 06 Aoû 2014, 9:19. Mais ma question concernait cette partie, pas l'ensemble du programme passé.
Je me perd dans le code. Trop peu d'aération et de commentaires généraux sur . Je continuerai l'étude plus tard.
---------------------- ti82statfr: 2008, inscrit: 2009, ti84pocketfr: noël2011, ti30xbmultiview: iut 2012-2014
Perfectionniste, manque tact. Pas le temps de tout publier depuis 2011. Répond toujours aux questions. (rédigé juin 2014)
Autorisation : Membre
Nb de messages : 3738
Inscrit le : Lun 19 Oct 2009, 21:25
Posté le : Ven 08 Aoû 2014, 16:27
Je constate que le modulo ne sert que pour l'affichage en deux dimensions puisque la liste est en une dimension. J'aurais apprécié que l'aération et un commentaire explique simplement que c'est pour l'affichage. Je connais bien les changements de repères mais je n'utilise jamais de déformation telle que ton 4.1 alors je me suis perdus tout seul.
L'absence d'indentation et d'aération du code m'a obligé à chercher moi-même les blocs. Cela devient pénible dans le traitement des déplacements.
Ta mise à 1 de la liste, pour repérer ce qui a déjà été sommé, m'ennuie. Je creuserai cela plus tard.
(Je préfère ma méthode (pas postée à ce jour) de chute des données : une boucle qui parcourt chaque colonne une seule fois, et pour chacune un pointeur qui repère le haut de la pile et une mémoire de la valeur du haut de la pile qui non-seulement permet de gagner du temps mais aussi avec une valeur impossible évite la combinaison d'une case qui vient à peine d'être combinée.)
Je n'ai aucun problème avec le concept des variables I,S,P. Tes commentaires aident bien sur ce point. Je suis enchanté de voir que quelqu'un a seul l'initiative d'optimiser avec une seule procédure et des variables, ce n'est pas courant chez ceux qui se présentent comme débutants.
(Mes propres travaux utilisent une matrice et trois méthodes différentes, donc je n'ai pas réfléchi au traitement dans une liste. Je dois d'abord maîtriser ce que tu fais avant de juger quoi que ce soit.)
##### L'affichage de la grille après chute.
J'optimise en utilisant une alternative plutôt que doubler la condition de nullité.
Saisir 22X-15 plutôt que -15+22X évite qu'un noob recopie de travers le symbole négatif, et évite de le traiter manuellement dans un éditeur de programme.
Tu peux actualiser l'affichage de toute la grille sans te limiter aux cases qui ont changées car tu ne perdras pas forcément de temps.
Si tu n'as aucun élément d'affichage à conserver (ce n'est pas ton cas puisque tu as un quadrillage) ou si tu peux les reconstituer rapidement (tu devrais utiliser une Pic/Img de la grille) alors efface tout l'écran et redessine le plutôt que d'effacer chaque case vide.
Utilise une boucle For au lieu d'une boucle While.
Saches que tu peux gérer les coordonnées (X;Y) en les incrémentant au lieu de calculer une division du compteur F.
Je te conseilles plutôt d'utiliser deux boucles, une pour X et une pour Y. Ensuite tu peux calculer F ou l'incrémenter. Si un jour tu abandonnes les listes au profit des matrices, tu auras avantage à faire comme ça sans besoin de F.
Indenté et avec une boucle For et une alternative.
Code
For(F,1,16
If LMU(F) =/= LOU(F)
Then
partEnt(F/4.1)+1->Y
F-partEnt(F/4.1)*4->X
If LMU(F
Then
Texte(14Y-4,22X-15,LMU(F
Else
Texte(14Y-4,22X-15," "
End
End
End
Code
0->X
1->Y
For(F,1,16
X+1->X
If X>4
Then
1->X
Y+1->Y
End
If LMU(F
Then
Texte(14Y-4,22X-15,LMU(F
Else
Texte(14Y-4,22X-15," "
End
End
Deux boucles For pour X et Y.
Code
For(Y,1,4
For(X,1,4
X+4Y-4->F
If LMU(F
Then
Texte(14Y-4,22X-15,LMU(F
Else
Texte(14Y-4,22X-15," "
End
End
End
---------------------- ti82statfr: 2008, inscrit: 2009, ti84pocketfr: noël2011, ti30xbmultiview: iut 2012-2014
Perfectionniste, manque tact. Pas le temps de tout publier depuis 2011. Répond toujours aux questions. (rédigé juin 2014)
Autorisation : Membre
Nb de messages : 4
Inscrit le : Mar 05 Aoû 2014, 22:28
Posté le : Ven 08 Aoû 2014, 23:31
Oui je suis désolé mais c'est très compliqué de rédiger un code qui soit à la fois clair et commenté... Je l'espacerai plus la prochaine fois. Mais le problème c'est que les espaces que je fais quand j'édite (pour faire des alinéas plus ou moins grandes selon la boucle conditionnelle sur laquelle on est) ne restent pas lorsque mon message est sur le site... Du coup c'est tout de suite moins compréhensible
Et pour ce qui est du passage :
If LMU(Q)=LMU(J)=LMU(J-P)=LMU(J-2P) et LMU(Q)=0
Then
4->W
End
Quand je disais que ça bugait, c'est que lorsque la calculette lis ce passage et que la condition est vérifiée, elle stoppe le 'scan' de la grille et retourne directement au moment où elle attend une pression de touche de notre part... Mais elle n'affiche pas d'ERREUR SYNTAXE en tout cas
Autorisation : Membre
Nb de messages : 3738
Inscrit le : Lun 19 Oct 2009, 21:25
Posté le : Sam 09 Aoû 2014, 1:03
Utilise une balise code car elle permet de mettre en évidence les codes et parce qu'elle respecte les espaces. [code*][*/code] sans les étoiles, et accessible par les icones au dessus du champ de texte d'écriture de message.
Je suis rassuré que tu sois quand même conscient de l'indentation.
Mon avis sur le manque de commentaires n'est que mon avis ! Commenter n'est pas évident et dépend du public. La distinction des parties est plus fondammentale, que ce soit par indentation ou commentaire.
Je prends l'initiative d'indenter ton code (éditer le message, modération powa) mais je ne touche qu'à ça.
Je me suis trompé en imaginant qu'il y aurait une erreur syntaxe car je n'ai pas pensé à toutes les lois de priorité.
Quoi qu'il en soit ma dernière balise du 7 août montre la correction : séparer les opérateurs de comparaisons en plusieurs termes.
If LMU(Q)=LMU(J) et LMU(Q)=LMU(J-P) et LMU(Q)=LMU(J-2P) et LMU(Q)=0
Sinon la priorité est interprétée comme ceci :
If ((( LMU(Q)=LMU(J) ) =LMU(J-P) ) =LMU(J-2P)) et LMU(Q)=0
Et chaque comparaison génère 0 ou 1 qui représente faux ou vrai.
If (( 0 =LMU(J-P) ) =LMU(J-2P)) et LMU(Q)=0
If ( 0 =LMU(J-2P)) et LMU(Q)=0
If 0 et LMU(Q)=0
J'ai repéré les blocs, mais je n'ai pas tout compris. Je continue l'étude de temps en temps par périodes.
---------------------- ti82statfr: 2008, inscrit: 2009, ti84pocketfr: noël2011, ti30xbmultiview: iut 2012-2014
Perfectionniste, manque tact. Pas le temps de tout publier depuis 2011. Répond toujours aux questions. (rédigé juin 2014)
Autorisation : Membre
Nb de messages : 3738
Inscrit le : Lun 19 Oct 2009, 21:25
Posté le : Dim 10 Aoû 2014, 19:25
Optimisations de la partie du déplacement, suivants mes obsession.
L'usage de For() synthétise des choses, mais ce n'est pas plus simple si les concepts ne sont pas adaptés à l'avance.
Code
Tu peux remplacer Z par W et garder les autres W. La fonction For du langage TI-Basic supporte cela car les paramètres sont interprétés une seule fois. Contrairement aux autres langages.
V sert à palier au fait que tu as pensé ton algorithme avec un incrément de W qui n'est pas la dernière action, contrairement à For(). Je ne voulais pas déplacer de commande ni changer de valeur initiale.
For(H,0,3
I->J
J+P->Q : 1->Z : 1->R //
If LMU(Q)=LMU(J) et LMU(Q)=LMU(J-P) et LMU(Q)=LMU(J-2P) et not(LMU(Q
Then //
4->Z
End
For(W,Z,3 //
For(R,V,1,-1 //
If LMU(Q //
Then
If LMU(Q)=LMU(J) et LNU(Q)=0 et not(LNU(J //
Then
LMU(Q)*2->LMU(J)
1->LNU(J)
0->LMU(Q)
Z+LMU(J)->Z
End
If not(LMU(J //
Then
LMU(Q)->LMU(J)
0->LMU(Q)
End
End
Q-P->Q : J-P->J //
End
W+1->V //
Q+VP->Q : J+VP->J //
End
I+S->I //
End
Je cherchais à assimiler ton algorithme de déplacement mais j'abandonne. L'optimisation superficielle suffira.
(Je pensais enrichissant de tout saisir puisque je n'ai jamais cherché à utiliser une liste au lieu d'une matrice.)
Il ne correspond pas à mes concepts mais peu importe car je ne compte pas remplacer tes algorithmes, surtout s'ils fonctionnent. Sinon ce seraient les miens et ce ne serait plus ton programme.
Maintenant que j'ai corrigé des syntaxes, optimisé des structures élémentaires, et abusé des économies de parenthèses, il est temps que tu testes si ton programme complet passé et ton nouvel algorithme aléatoire fonctionnent. Soit dit en passant, le programme complet doit certainement fonctionner puisque tu as signalé une seule ligne comme défectueuse (celle de multiples égalités).
++++
++++
Je m'attarderai maintenant sur ton dernier code d'aléatoire. C'est ce pourquoi tu as posté au départ et on ne sait toujours pas s'il fonctionne.
Je suis persuadé que tu commets un défaut de raisonnement mais je ne suis toujours pas certain de ce que tu fais ou crois faire.
Tu sembles confondre la liste des données, ici L6, avec ce qui serait un index, c'est-à-dire une liste des cases libres (ou occupées mais cela ne convient pas au besoin d'efficacité), c'est-à-dire une liste de pointeurs vers les cases libres.
Et j'avais déjà déconseillé la méthode de l'index, qui ne me plait pas.
Selon moi, avec un index des cases libres, il faudrait que :
-l'index soit initialisé plein
-lorsqu'une nouvelle donnée est insérée, le pointeur vers cette case soit recherché dans l'index, puis ce pointeur soit éliminé de l'index
-lorsqu'une case de donnée est déplacée, un pointeur vers la donnée remplace celui vers l'ancienne case libre
-lorsqu'une case de donnée est fusionnée à une autre, le pointeur vers la donnée soit éliminé
-la procédure de choix aléatoire de case libre lise l'index à une adresse aléatoire, donc lise un pointeur vers une case libre, ce qu'on veut générer
Malgré toutes ces considérations, modifier l'index lui-même ne sera pas aussi optimisé qu'on l'espérerait dans un autre langage. Et même dans un autre langage, il y aurait des pour et des contres.
La mise à jour de l'index doit être réalisée à chaque déplacement de une ou plusieurs données.
Je conseille de la réaliser progressivement dans la section de déplacement des données.
Mais chaque cases déplacée devrait l'être en une seule fois, et je ne suis pas certain que ce soit le cas actuellement. Sinon les pertes de temps par mise à jour d'index seront multipliées.
Je n'apprécie pas de mettre à jour tout l'index une seule fois par itération de la boucle principale (ici ton Goto A final du programme). Une telle mise à jour d'index demanderait de parcourir toute la liste et pour chaque case adéquate, stocker un pointeur. Le parcourt peut être contrôlé par la boucle de mise à jour d'écran qui justement parcourt déjà la liste de données.
Ci-dessous ma solution avec mise à jour progressive de l'index.
Code
// Je ne m'encombre pas avec la taille de la liste, je modifie le contenu et une information du nombre de données, mais je ne vide jamais la mémoire occupée par la liste.
suite(W,W,1,16->L6 // {0,1,2,3,...,16}
16->E
Lbl A
entAléat(1,E->C
L6(C->A
For(W,C,E-1 // déplacement de la fin de l'index pour éliminer le pointeur
L6(W+1->L6(W
End
E-1->E
..........
If LMU(Q) =/= 0
Then
If LMU(Q)=LMU(J) et LNU(Q)=0 et LNU(J)=0
Then
LMU(Q)*2->LMU(J)
1->LNU(J)
0->LMU(Q)
Z+LMU(J)->Z
E+1->E // ajout dans l'index d'un pointeur vers la nouvelle case libre
Q->L6(E
End
If LMU(J)=0
Then
LMU(Q)->LMU(J)
0->LMU(Q)
0->B // recherche dans l'index
Repeat J=L6(B
B+1->B
End
Q->L6(B // mise à jour de l'index
End
End
..........
---------------------- ti82statfr: 2008, inscrit: 2009, ti84pocketfr: noël2011, ti30xbmultiview: iut 2012-2014
Perfectionniste, manque tact. Pas le temps de tout publier depuis 2011. Répond toujours aux questions. (rédigé juin 2014)