Discuss Scratch

SBissay
Scratcher
500+ posts

[Tuto] Stocker des données de longueur variable dans une variable cloud

Bonjour à tous !

Lors de mes pérégrinations avec les variables cloud, outre le stockage des noms d'utilisateurs ou autres chaines de caractères (sujet abordé en de nombreux endroits (ici par exemple), je me suis frotté à un autre problème et je me suis dit que je partager les solutions que j'ai trouvées pourrait peut-être en aider certains.

Voici le problème : comment dans une variable cloud stocker une suite de nombres dont je ne connais pas la longueur a priori ?
Petite précision : c'est bien de nombres que je ne connais pas la longueur, ne pas connaître celle de la suite n'est aucunement un problème.

Et bien, la meilleure réponse que j'ai trouvée est : ça dépend.

Voilà, merci pour votre attention.



Ah, on me fait signe que je n'en ai pas dit assez. Donc, voici une réponse plus détaillée :
ça dépend de ce que je sais de la longueur que peuvent avoir ces nombres.

Et pour être encore plus précis, il y a deux cas distincts.

1er cas : Mes nombres ont une longueur variable (sinon je n'aurais pas eu à me poser de questions), mais celle-ci ne va pas dépasser une certaine longueur, j'en suis sûr à 100%.

Exemples :
  • Un (mauvais) exemple : je veux stocker des scores, mais vu la façon dont mon jeu est fait, ils seront tous compris entre 1 et 1000. Alors, c'est un exemple de la situation dans laquelle je ne connais pas la taille des nombres, mais je sais qu'ils font tous 4 chiffres au plus (le nombre de chiffres pour écrire 1000 étant 4… pour les plus matheux, la formule donnant le nombre de chiffres pour écrire un nombre x (en base 10) est : nombre = E( ln(x) / ln(10)) + 1, où E est la fonction partie entière et ln est le logarithme népérien). Bref, ça rentre dans notre cas, mais ça reste un mauvais exemple parce que 4 chiffres ce n'est pas énorme et donc on peut très bien tous les stocker sur 4 chiffres, en ajoutant des 0 devant le nombre voulu s'il fait moins de 4 chiffres.
  • Un (meilleur) exemple : je dois stocker des nombres dont la longueur est comprise entre 1 et 100 chiffres (ne me demandez pas pourquoi, je dois le faire, c'est tout). Alors là, et surtout si la plupart de mes nombres sont plutôt courts, ce serait une grosse perte de place sur la variable cloud (dont la longueur est limitée) de tout stocker sur 100 chiffres. Une bonne solution consiste alors à stocker mes nombres en stockant juste avant leur longueur, qui elle ne devrait pas trop prendre trop de chiffres et est donc stockable en suivant la méthode de l'exemple précédent.
    Ainsi, si la longueur de mes nombres ne peut pas dépasser 99, je peux stocker leur longueur sur deux chiffres, et du coup la valeur : 0392112235426789104 se lirait de la façon suivante : “03” -> le premier nombre a une longueur de 3 chiffres, je lis donc les 3 chiffres suivants : “921”, puis les deux nombres suivants sont la longueur du prochain nombre : “12”, donc je lis les 12 prochains chiffres qui sont : “235 426 789 104” et là ma variable est finie donc j'ai tout lu.

    voici un exemple de décodage de cette solution :
    mettre [NbChiffresLongueur v] à [le nombre de chiffres qu'il faut pour écrire votre longueur maximale]
    mettre [Index v] à [1]
    répéter jusqu’à <(longueur de (☁ cloud)) < (Index)>
    mettre [Longueur v] à [] //<- c'est vide
    répéter (NbChiffresLongueur) fois
    mettre [Longueur v] à (regroupe (Longueur) (lettre (Index) de [(☁ cloud)]))
    ajouter à [Index v] (1)
    end
    mettre (Nombre v) à [] //<- c'est vide aussi
    répéter(Longueur) fois
    mettre (Nombre v) à (regroupe (Longueur) (lettre (Index) de [(☁ cloud)]))
    ajouter à [Index v] (1)
    end
    ajouter (Nombre) à [listeValeurs v]
    end

    Et pour ajouter une valeur à la variable cloud, il suffit de :
    mettre [Longueur v] à (([plancher v] de (([ln v] de (Nombre)) / ([ln v] de (10)))) + (1))
    répéter ((NombreChiffresLongueur) - (([plancher v] de (([ln v] de (Longueur)) / ([ln v] de (10)))) + (1))) fois
    mettre [Longueur v] à (regroupe (0) (Longueur))
    end
    mettre [☁ cloud v] à (regroupe (☁ cloud) (regroupe (Longueur) (Nombre)))

2ème cas : Mes nombres n'ont pas de longueur maximale connue au moment où je crée mon programme (très très rare, mais sait-on jamais).
Alors dans ce cas, j'ai une ruse de sioux à vous proposer : utiliser la base 9 !

La base 9, kézako ?
Ça revient à écrire votre nombre sous forme de restes de divisions euclidiennes successives par 9. SI vous n'avez RIEN compris à ce que je viens de dire, pas de panique, c'est pas grave.

Ce qu'il est important de comprendre, c'est que dans notre façon habituelle d'écrire les nombres, on utilise 10 chiffres : 0, 1, 2, …, 8, 9. On l'appelle bizarrement, la base 10. Les plus perspicaces d'entre vous pourront peut-être y voir un lien… Et là, magie, en base 9 on n'utilise que 9 chiffres : 0, 1, 2, 3, 4 ,5 ,6 ,7, 8. Le 9 ne peut pas apparaître. Et donc, une fois en base 9, il est très facile de séparer deux nombres… en insérant un “9” en tant que délimiteur !

Bon, je ne vais pas vous faire un cours sur le passage de la base 10 à la base 9 et vice-versa, donc voici du code :

pour passer de la base 10 à la base 9 :
définir Vers base9 (n)
mettre [NouveauNombre v] à [] //<- c'est vide
mettre [Temporaire v] à (n)
répéter jusqu’à <(Temporaire) = (0)>
mettre [NouveauNombre v] à (regroupe (((Temporaire) modulo (9)) + (1)) (NouveauNombre)
mettre [Temporaire v] à ([plancher v] de ((Temporaire) / (9))
end

Pour en revenir :
définir Vers base10 (n)
mettre [Nombre v] à [0]
mettre [Temporaire v] à (n)
mettre [Index v] à (longueur de (n))
répéter (longueur de (n)) fois
ajouter à [Nombre v] (((lettre (Index) de (n)) - (1)) * (Temporaire))
mettre [Temporaire v] à ((Temporaire) * (9))
ajouter à [Index v] (-1)
end

Et avec ça, vous êtes assez grands pour insérer des “9” entre les différentes valeurs

Voilà, j'espère que ça vous sera utile, et n'hésitez pas si vous avez des questions.

Last edited by SBissay (March 11, 2017 10:49:22)


Generative art :              Pivot  :               Sudoku :
smrman
Scratcher
1000+ posts

[Tuto] Stocker des données de longueur variable dans une variable cloud

Pas mal comme idée.
Perso j'aurais eu tendance à utiliser une séquence bien particulière de chiffre pour détecter un espacement ou qqch qui marque un changement, comme une suite de 5 chiffres 9 à la suite.
Mais je me dis qu'il y a aussi une proba pour que cette séquence se retrouve naturellement dans la variable.
Donc surmenet pas la meilleur option pour une longueur connue mais ça pourrait aller avec une longueur inconnue de caractères.

SBissay
Scratcher
500+ posts

[Tuto] Stocker des données de longueur variable dans une variable cloud

Oui, le délimiteur a toujours un risque d'apparaître dans les valeurs à stocker, c'est pour ça que j'ai cherché des solutions alternatives. Après, si on est sûr - pour une raison x ou y - que la séquence “424242” (par exemple) ne peut pas apparaître, alors il est évident que l'on peut s'en servir comme délimiteur et éviter toute cette prise de tête.

Generative art :              Pivot  :               Sudoku :
Itharius
Scratcher
1000+ posts

[Tuto] Stocker des données de longueur variable dans une variable cloud

Un petit Up de topic ! ^^ Je cherche à stocker des listes de nombres malgré la limitation donc je suis revenu à ce topic (que je n'avais pas et que je n'ai toujours pas d'ailleurs complètement compris ^^).

Bon , il est clair que vu la limitation , c'est fini le stockage de nombre de longueur de 100 chiffres ^^ mais je voudrais quand même continuer d'utiliser les variables cloud pour faire des trucs…

Donc pour mon prochain projet, j'ai mis en place ce petit système:

Etant donné que je ne cherche à stocker que des chiffres ( pas de lettres) et vu la limitation du cloud , ce serait une énorme perte que de devoir coder 1 chiffre avec 2 chiffres pour pouvoir bénéficier d'un séparateur par exemple. Donc mon idée est de coder la longueur de l'élément et l'élément.

Ok , je vois la protestation , ça reste 2 chiffres pour coder 1 chiffre ^^ oui mais, c'est quand même un gain de place étant donné que je remplace un séparateur de 2 chiffres par 1 chiffre ^^ donc dans le systeme classique précédent un élément de 1 chiffre prenait 4 chiffres ( 2 chiffres pour l'élement à 1 chiffre + 2 chiffres pour le séparateur), dans le système que je propose ça prend 2 chiffres ( 1 chiffre qui fait office de séparateur et 1 chiffre pour l'élément ) ^^

ça permet donc de stocker des nombres dont on ne connait pas la longueur à l'avance.
j'ai également rajouter un petit trick comme pour refaire fonctionner mon highscore de mon jeu Battle Tank Duel (Pub ^^)

l'exemple du codage/décodage https://scratch.mit.edu/projects/123690916

(j'aurais pu rajouter 2 variables temporaires au lieu de travailler directement sur les variables cloud, ça ferait moins bordel dans le panneau des cloud activity mais c'est juste une illustration )

Last edited by Itharius (Nov. 22, 2018 17:27:02)

bidulule
Scratcher
1000+ posts

[Tuto] Stocker des données de longueur variable dans une variable cloud

tu as estimé le gain de place que ça te fait ? pasque sur plein de données, ça va certainement être efficace mais sur 128 caractères….

Itharius
Scratcher
1000+ posts

[Tuto] Stocker des données de longueur variable dans une variable cloud

ben c'est déjà énorme parce que ce que j'estime , c'est que je vais avoir besoin de stocker environ 64x4x2 caractères,soit 4variables clouds au lieu de devoir utiliser les 10 variables pour la même place.
SBissay
Scratcher
500+ posts

[Tuto] Stocker des données de longueur variable dans une variable cloud

Itharius wrote:

Un petit Up de topic ! ^^ Je cherche à stocker des listes de nombres malgré la limitation donc je suis revenu à ce topic (que je n'avais pas et que je n'ai toujours pas d'ailleurs complètement compris ^^).

Bon , il est clair que vu la limitation , c'est fini le stockage de nombre de longueur de 100 chiffres ^^ mais je voudrais quand même continuer d'utiliser les variables cloud pour faire des trucs…

Donc pour mon prochain projet, j'ai mis en place ce petit système:

Etant donné que je ne cherche à stocker que des chiffres ( pas de lettres) et vu la limitation du cloud , ce serait une énorme perte que de devoir coder 1 chiffre avec 2 chiffres pour pouvoir bénéficier d'un séparateur par exemple. Donc mon idée est de coder la longueur de l'élément et l'élément.

Ok , je vois la protestation , ça reste 2 chiffres pour coder 1 chiffre ^^ oui mais, c'est quand même un gain de place étant donné que je remplace un séparateur de 2 chiffres par 1 chiffre ^^ donc dans le systeme classique précédent un élément de 1 chiffre prenait 4 chiffres ( 2 chiffres pour l'élement à 1 chiffre + 2 chiffres pour le séparateur), dans le système que je propose ça prend 2 chiffres ( 1 chiffre qui fait office de séparateur et 1 chiffre pour l'élément ) ^^

ça permet donc de stocker des nombres dont on ne connait pas la longueur à l'avance.
j'ai également rajouter un petit trick comme pour refaire fonctionner mon highscore de mon jeu Battle Tank Duel (Pub ^^)

l'exemple du codage/décodage https://scratch.mit.edu/projects/123690916

(j'aurais pu rajouter 2 variables temporaires au lieu de travailler directement sur les variables cloud, ça ferait moins bordel dans le panneau des cloud activity mais c'est juste une illustration )

C'est marrant que tu n'aies pas tout compris, parce que moi, à la première lecture, je n'ai RIEN compris de ton système…

Heureusement il y a un projet lié (ça m'a bien aidé à saisir ce qui te semblait évident).
De ce que j'ai compris : tu prends un nombre, et tu écris sa longueur puis le nombre.
C'est parfait… Tant que tu es sûr qu'aucun nombre ne dépassera 9 chiffres de long.
Sinon, la longueur du nombre ne sera lue que sur 1 chiffre, et ça va tout fiche en l'air (j'ai fait le test sur ton système : met le premier élément de la liste à un nombre à 10 chiffres (genre 1234567890), encode et décode, tu auras des surprises).

Bref, si tu es SÛR à 100% que ça n'arrivera pas, ton système est parfait. Sinon la base 9 me semble un moindre mal.

Edit : par contre je cherche où tu as vu un séparateur de longueur 2 dans mon post.

Re-edit : au passage, c'est quand même la première méthode que j'ai proposé. Sauf qu'au lieu d'être sûr d'avoir des nombres de moins de 100 chiffres, tu pars du postulat qu'ils feront moins de 10 chiffres, et donc tu n'as besoin de stocker qu'un chiffre pour la longueur.

Last edited by SBissay (Nov. 22, 2018 19:57:16)


Generative art :              Pivot  :               Sudoku :
Itharius
Scratcher
1000+ posts

[Tuto] Stocker des données de longueur variable dans une variable cloud

arf oui ! j'ai complètement zappé si l'élément fait une longueur de 10 chiffres
Bon je suis pas prêt de compter en milliard non plus ^^ une autre chose que mon système ne prend pas en compte (je viens de m'en rendre compte ^^) ce sont les nombres à virgule
SBissay
Scratcher
500+ posts

[Tuto] Stocker des données de longueur variable dans une variable cloud

Pour les nombres à virgule, ça complique la chose (et ça prend plus de place).

Une solution serait de stocker l'emplacement de la virgule après la longueur, avec une virgule placée “à la fin” pour un entier.

Ce sera plus parlant avec un exemple :
10.34 - > 421034.
A lire :
4 - il y a 4 chiffres (je repars du postulat que rien ne dépassera 9 chiffres, même avec la virgule, sinon faut stocker à la fois la longueur et l'emplacement de la virgule sur plus de chiffres)
2 - la virgule est après le 2ème chiffre
1034 - le nombre, et on lui rajoute la virgule après le 2ème chiffre, donc 10.34

autre exemple :
143 -> 33143
3 car il y a 3 chiffres
3 car la virgule est après le dernier (= 3ème) chiffre
et 143 le nombre.

On constate qu'un entier aura toujours deux fois le même chiffre au début de l'encodage.

Enfin, on peut stocker 0.5 par 105 :
1 chiffre, la virgule après le 0ème chiffre (et donc en fait au début) et puis juste 5, ça donne .5 qui est bien égal à 0.5.

Une autre possibilité est repasser le nombre à virgule en entier en le multipliant par une puissance de 10, et de stocker la puissance de 10 en question pour diviser par elle.
Exemple :
10.34 -> 221034
2 chiffres
on doit diviser par 10^2
1034 / 10^2 = 10.34

13 -> 2013
2 chiffres
diviser par 10^0
13 / 10^0 = 13

0.005 -> 135
1 chiffre
diviser par 10^3
5 / 10^3 = 0.005

Last edited by SBissay (Nov. 22, 2018 20:16:24)


Generative art :              Pivot  :               Sudoku :
swannator2005
Scratcher
1 post

[Tuto] Stocker des données de longueur variable dans une variable cloud

ma15fo43
Scratcher
1000+ posts

[Tuto] Stocker des données de longueur variable dans une variable cloud

Bonjour et bienvenue dans le forum francophone Scratch.
Comme tu peux le voir à la date du dernier post de ce topic, il commence à se faire vieux et il est inutile de le faire remonter pour ce genre de commentaire inutile (ton post est… vide?).
Merci de respecter les règles du forum.

No longer active on Scratch, I build stuff with TypeScript and Kotlin nowadays. (#3 all-time poster in French forums)
AK_Scratcher_54
Scratcher
100+ posts

[Tuto] Stocker des données de longueur variable dans une variable cloud

swannator2005 wrote:

wow















Powered by DjangoBB