Seuls les membres ayant 30 points peuvent parler sur le chat.

Rewind 2010-2019

Découvrez les événements, projets et membres majeurs qui ont guidé Planète Casio pendant 10 ans !

Le Jeu du Mois

Deux programmes sont arrivés premier ex-aequo. Nous avons alors deux Jeux du mois !

Fxgnuboy de Djpadbit a remporté le titre du Jeu du mois d'Octobre 2020 !

Game Of Life de CaptainLuigi a remporté le titre du Jeu du mois d'Octobre 2020 !

Nos projets majeurs

Voir le forum des projets
Proposer un article pour la RDP

Réseaux sociaux et partenaires

Bienvenue sur Planète Casio !

Planète Casio est la communauté française de référence pour toutes les calculatrices Casio. Apprenez à utiliser votre machine, téléchargez et partagez des programmes, ou initiez-vous à l'informatique sur le forum. Ou bien venez développer des jeux avec nous pour passer le temps !

Événements à venir

  • Une semaine de test de programmes
  • Une réunion de Planète Casio

Actualités

TDM 18 : Comprendre les données et leurs représentations


Le Tutoriel du Mercredi (TDM) est une idée proposée par Ne0tux, qui recouvre tous les usages de la calculatrice - des applications de Casio à la conception de jeux en passant part la production artistique.

Aujourd'hui, on explore la notion de données dans les add-ins !

Ce tutoriel fait partie des publications de l'Avent 2020.

Niveau ★ ★ ★ ☆ ☆ (Lycée/Terminale selon les parties)
Tags : Données, Conversion, Représentation, C

Bienvenue dans ce tutoriel ! Si vous vous êtes déjà demandé « comment convertir un fichier en binaire ? », avez essayé d'afficher un entier avec Print(), de convertir un fichier g1a en g1m, ou n'arrivez simplement pas à mettre le doigt sur ce à quoi sert l'hexadécimal, vous êtes au bon endroit.

Aujourd'hui, on va parler de ce que sont les données, de ce qui est (et n'est pas) une conversion, et aborder en même temps les questions de formats de données et de fichiers. Ce sont des choses que les langages de programmation essaient de cacher la plupart du temps parce qu'on a rarement besoin de s'en soucier, donc quand ce moment arrive il est facile d'être perdu.

Ce tutoriel vous aidera à comprendre ce qui se cache vraiment derrière vos variables, images et fichiers, et à distinguer les changements de représentation des conversions. Vous verrez qu'en C en particulier il y a quelques subtilités !

Sommaire
Les données numériques : que des 0 et des 1
Grouper pour mieux régner : la représentation hexadécimale
Entiers en base 2 et en base 16
Types de données : une variété de tailles et de rôles
Interprétation des données : pourquoi on type les variables et les fichiers
Représentation des données : comment afficher ses variables
Conversions : ce qui en est et ce qui n'en est pas
Les conversions impossibles : ne pas se tromper sur le type
Conclusion


Les données numériques : que des 0 et des 1

Dans un ordinateur, la nature des données est facile : tout est fait de 0 et de 1. Ce texte que vous lisez est fait de 0 et 1. Le score maximal que vous venez d'enregistrer dans votre jeu favori est fait de 0 et de 1. La musique que j'écoute, les pixels qui sont affichés sur votre écran, tous les fichiers présents sur nos disques durs... tout est fait de 0 et de 1.

La raison pour ça est simple : un ordinateur fonctionne avec des signaux de tension électrique, et plus il y a de valeurs différentes plus le risque que le circuit électronique transforme une valeur en une autre par un phénomène physique est élevé. Dans une puce où le 0 est représenté par une tension de 0 V et le 1 est représenté par une tension de 3.3 V (par exemple), on arrive à s'en sortir et à éviter que les 0 ne se changent en 1 juste parce que du courant fuite ou parce qu'un champ magnétique autour du processeur modifie le fonctionnement du circuit.

Vous savez certainement qu'on appelle ça le système binaire, et que chaque 0 ou 1 est appelé un bit. Si vous dites « données numériques » ou « données binaires » ça revient au même : une longue liste de bits. La première chose que vous pouvez retenir est donc que :

Retenez Toutes les données qui existent dans un ordinateur sont binaires. « Convertir en binaire » est donc une notion un peu absurde, car l'objet que vous essayez de convertir est déjà en binaire.



Grouper pour mieux régner : la représentation hexadécimale

Les bits c'est pratique pour un ordinateur, mais pas pour un humain. Les ordinateurs sont conçus pour différentier 0 V et 3.3 V, et c'est tout. Mais les humains sont capables de différencier bien plus que ça : par exemple quand on lit on est aisément capables de différencier 10 chiffres et 26 lettres. Par contre, on peut vite faire des erreurs de lecture, surtout s'il y a plein de chiffres qui se répètent. Par exemple, si je vous fais lire

10011010100010000000000111110001,

il est probable que vous ayez besoin de vous y reprendre à deux fois pour énoncer le bon nombre de 0 dans la longue séquence du milieu. Et vous serez incapable de répéter la séquence sans la lire une deuxième fois. Tandis que si je vous fais lire

9a8801f1,

vous allez le prononcer correctement du premier coup et vous pourrez peut-être même répéter la séquence sans la relire. Pour un humain, c'est beaucoup plus facile de lire, analyser et communiquer des données sous cette forme.

Le deuxième texte ci-dessus est la représentation hexadécimale de la chaîne de bits qui précédait. C'est juste une représentation parce que les données sont les mêmes, je les ai juste écrites différemment, avec une notation différente. En particulier, comme je n'ai pas changé les données il n'y a pas eu de conversion (on en reparle plus tard).

Comment est-ce que ça marche ? La représentation hexadécimale consiste à grouper les bits par 4 et à associer un caractère différent à chacune des 16 combinaisons possibles. La correspondance se fait comme ceci :


Et donc, si on reprend la donnée de tout à l'heure, on peut découper en paquets de 4 bits et remplacer chaque paquet par le caractère qui va bien.


De la même façon, on peut repartir de la chaîne hexadécimale et re-développer en binaire pour récupérer les bits d'origine. On n'a fait que changer l'écriture, les données sont parfaitement intactes. Le format hexadécimal est simplement plus agréable à lire pour les humains.


Retenez L'hexadécimal est utilisé pour afficher des données binaire sous une forme compacte et facile à lire pour les humains.

Si vous faites un peu de programmation bas-niveau en C ou en assembleur, ou que vous décortiquez des fichiers exécutables, ou inspectez des fichiers dont vous ne connaissez pas le type, alors il y aura de l'hexadécimal partout. Parce que dans toutes ces situations il y a des données à représenter, et à défaut de mieux l'hexadécimal est utilisé pour vous les montrer, en espérant que ce sera agréable à lire pour vous.

Par exemple, si j'affiche le contenu du fichier texte dans lequel j'ai enregistré le texte de ce tutoriel avec l'outil Linux xxd, j'obtiens ce résultat.

00000000: 2320 5444 4d20 3138 203a 2043 6f6d 7072  # TDM 18 : Compr
00000010: 656e 6472 6520 6c65 7320 646f 6e6e c3a9  endre les donn..
00000020: 6573 2065 7420 6c65 7572 7320 7265 7072  es et leurs repr
00000030: c3a9 7365 6e74 6174 696f 6e73 0a0a 5b69  ..sentations..[i
00000040: 5d4c 6520 5475 746f 7269 656c 2064 7520  ]Le Tutoriel du
00000050: 4d65 7263 7265 6469 2028 5444 4d29 2065  Mercredi (TDM) e
00000060: 7374 2075 6e65 2069 64c3 a965 2070 726f  st une id..e pro
00000070: 706f 73c3 a965 2070 6172 205b 7072 6f66  pos..e par [prof
00000080: 696c 5d4e 6530 7475 785b 2f70 726f 6669  il]Ne0tux[/profi
(...)

Si on ignore pour l'instant les colonnes de gauche et de droite, vous pouvez voir que xxd m'a affiché les bits de mon fichier, groupés par 4 en hexadécimal. Ainsi j'ai pu accéder à la donnée qu'est le texte de ce TDM. Et on va voir tout à l'heure que le résultat n'était pas facile à prédire, car il y a plein de façons d'associer une donnée binaire à un texte.



Entiers en base 2 et en base 16

Vous savez certainement que la spécialité des ordinateurs c'est le calcul, et le calcul ça commence par les entiers. Les ordinateurs ont donc leur propre méthode pour représenter des entiers avec des bits. Ce n'est qu'une des innombrables choses qu'on utilise quotidiennement sous forme binaire (texte, images, musiques, vidéos, programmes, nombres réels, et caetera), mais ils sont si importants qu'ils ont d'office leur place dans ce tutoriel.

Le principe pour écrire des nombres avec des bits est similaire à la façon dont on les écrit en décimal. En décimal, les chiffres des unités représente un nombre de « 1 » à ajouter au total, le chiffre des dizaines représente un nombre de « 10 » à ajouter au total, celui des centaines un nombre de « 100 »... et ainsi de suite. On peut donc décomposer un nombre sur ces puissances de 10 successives.


On peut faire pareil en base 2, mais pour que ça marche chaque bit doit représenter une puissance de 2 au lieu d'une puissance de 10. Ainsi le premier bit représente un nombre de « 1 » à ajouter un total, le suivant un nombre de « 2 », le troisième un nombre de « 4 »... et ainsi de suite. Voici un exemple.


On peut prouver (ce n'est pas très difficile) que tous les nombres entiers peuvent s'écrire en base 2, et ce de façon unique. Autrement dit, il y a une correspondance complète entre les séquences de chiffres en base 10 et les séquences de chiffres (bits) en base 2. C'est très pratique parce que ça veut dire que si vous avez un nombre vous pouvez l'écrire en base 10 ou en base 2 selon le contexte, et il n'y a aucun risque d'ambiguïté.

Si tout ça vous paraît un peu confus, vous pouvez considérer cette analogie avec des images. Quand vous avez une image, vous pouvez l'enregistrer (entre autres) au format PNG ou au format BMP ; ces deux formats sont équivalents, car ils enregistrent fidèlement toutes les images. Le PNG est plus compact, mais le BMP est plus facile à coder. De la même façon, quand vous avez un entier, vous pouvez l'écrire en base 10 ou en base 2 ; ces deux bases sont équivalentes, car elles encodent fidèlement tous les entiers. La base 10 est plus naturelle pour les humains, mais la base 2 plus naturelle pour les machines.

Pour ne pas confondre 10 « dix » en décimal et 10 « un-zéro » en binaire (qui vaut deux), il est courant de mettre un préfixe devant les nombres écrits en binaire. En C/C++ (avec GCC), ce préfixe est « 0b » (zéro-b), et donc on écrit :

0b10 = 2, 0b0110 = 6, 0b11011000001 = 1729.

Quand il n'y a pas de préfixe on sous-entend que c'est en base 10.

Cette propriété qu'on peut écrire les nombres en base 10 et 2 n'est pas spécifique aux nombres 10 et 2 ; ça marche avec toutes les nombres. On peut aussi écrire les entiers de façon unique en base 7, ou les chiffres comptent pour 1, 7, 49... mais personne ne le fait parce que ce n'est naturel ni pour les humains ni pour les machines.

Cette nouvelle information permet de voir la représentation hexadécimale sous un autre angle. En effet, si vous regardez les séquences de 4 bits comme des nombres, vous pouvez voir que les caractères utilisés dans la représentation hexadécimale ne sont pas anodins :


Les caractères de la représentation hexadécimale sont en fait 16 chiffres représentant les valeurs de 0 à 15. Le fait qu'on utilise des lettres ne doit pas vous tromper, car le principe est vraiment le même qu'avec les autres bases :

• En base 2, il y a 2 symboles représentant les valeurs de 0 à 1.
• En base 10, il y a 10 symboles représentant les valeurs de 0 à 9.
• En base 16, il y a 16 symboles représentant les valeurs de 0 à 15.

Maintenant qu'on a 16 symboles sous la main on peut écrire des nombres en base 16 exactement comme on les écrivait en base 10 et en base 2.


De la même façon qu'on utilie le préfixe 0b pour distinguer les nombres en base 2, on a le préfixe « 0x » (zéro-x) pour les nombres en base 16. On écrit donc :

0xf = 15, 0x100 = 256, 0x6c1 = 1729, 0x27f3 = 10227.

Comme on ne risque plus de confondre, on peut maintenant écrire sans se tromper le même nombre dans plusieurs bases :

0b11011000001 = 1729 = 0x6c1.

En général on écrit rarement les nombres en base 2 et beaucoup plus souvent en base 16, car :

• Tout comme la représentation hexadécimale, c'est plus compact et plus facile à lire pour les humains.
• On a rarement besoin de savoir quels bits précis sont dans un entier.
• L'hexadécimal est déjà utilisé pour afficher les données binaires, c'est pratique d'avoir un seul format.

Retenez Les ordinateurs écrivent leurs entiers en base 2 ; ils ne savent manipuler que des 0 et des 1 donc c'est le plus naturel pour eux.
Retenez Les humains écrivent leurs entiers en base 10 ou 16 ; la base 10 est très naturelle car on apprend à compter avec, et la base 16 ressemble à la base 2 mais en plus compact et lisible.

Interlude pour ceux qui veulent réfléchir.
J'ai expliqué dans cette section comment une séquence de bits peut être vue comme un entier écrit en base 2, et comment une séquence de caractères hexadécimaux peut être vue comme un entier en base 16.

J'ai aussi mentionné dans la section précédente qu'on peut passer d'une séquence de bits à une séquence de caractères hexadécimaux en groupant les bits par 4.

Vous noterez que dans l'exemple ci-dessus, si on groupe les bits de 11011000001 par quatre (en ajoutant un zéro à gauche pour obtenir un multiple de 4), on obtient la donnée 0110 1100 0001, dont la représentation hexadécimale est 6c1.

En fait si on écrit un entier en base 2, qu'on représente la séquence de bits sous sa forme hexadécimale, et qu'on tente de lire le résultat comme un entier écrit en base 16, on obtient l'entier d'origine (et pareil dans l'autre sens). Par exemple, si on regarde la première séquence mentionnée dans ce tutoriel :

0b10011010100010000000000111110001 = 2592604657 = 0x9a8801f1.

Ainsi, si on a des données qu'on pense être un entier, on peut calculer la valeur de cet entier peu importe si les données sont affichées en binaires ou en hexadécimal : le résultat sera le même. (Et ce n'est pas un hasard, c'était prévu depuis le début !)
Fin de l'interlude.



Types de données : une variété de tailles et de rôles

Jusqu'ici, on a vu que les ordinateurs ne travaillent qu'en binaire, et on a vu comment ils s'y prennent pour écrire des entiers en binaire. Cette façon d'écrire en base 2 était connue bien avant qu'on commence à s'en servir dans les machines et est tombée à pic quand l'électronique à commencé à se développer.

Entiers non signés de 8, 16, 32 et 64 bits

Mais il y a un petit défaut : tous les nombres ne prennent pas la même place à écrire. Certains nombres prennent 3 bits comme 0b101 = 5, tandis que d'autre ont besoin de 5 bits comme 0b10011 = 19. L'électronique du processeur ne peut pas se permettre de changer de taille d'une fois sur l'autre, donc les ingénieurs se sont mis d'accord pour utiliser une seule taille : 8 bits.

Tout comme les nombres sur 3 chiffres en décimal vont de 000 à 999, les nombres sur 8 bits en binaire vont de 0b00000000 à 0b11111111 = 255. L'intérêt de 8 bits c'est que ça correspond tout pile à 2 chiffres en hexadécimal, et donc ces nombres sur 8 bits correspondent tout pile aux nombres entre 0x00 et 0xff en hexa.

Ce format est devenu tellement courant qu'il a maintenant un nom : octet (ou byte en anglais). On appelle octet toute séquence de 8 bits, que cette séquence soit utilisée comme un entier ou non. Ce groupement a même influencé la façon dont la mémoire (par exemple la RAM) est conçue, si bien qu'en pratique on ne mesure jamais rien en nombre de bits, on mesure tout en nombre d'octets. À tel point que si une donnée occupe un nombre de bits qui n'est pas multiple de 8 on rajoute des 0 pour arrondir à l'octet supérieur !

Retenez L'archétype de l'entier est un entier non-signé sur 8 bits (1 octet), et peut représenter les nombres de 0 à 255.
Retenez L'octet est devenu tellement fondamental qu'on compte désormais tout en octets et non en bits.

Les processeurs passent énormement de temps à faire du calcul sur les entiers et ont tous une taille préférée. Ceux qui utilisent des entiers 8 bits dans leur calcul sont appelés aujourd'hui des processeurs 8-bit, ils appartiennent à une époque glorieuse (notamment marquée par l'icônique Intel 8086) mais révolue. Parce que comme vous pouvez vous en douter, compter jusqu'à 255 c'est marrant deux minutes mais ça ne nous emmène pas particulièrement loin.

Les processeurs ont donc évolué et avec le temps se sont mis à calculer avec des entiers plus gros : d'abord 16 bits (2 octets), puis 32 bits (4 octets), puis 64 bits (8 octets). La raison pour laquelle on ne veut que des nombres d'octets qui sont des puissances de 2 est liée au fonctionnement de la mémoire, j'en parlerai sans doute dans le TDM 19 (celui-ci est déjà assez long !).

Retenez On trouve couramment des entiers de 16, 32 et 64 bits, chacun pouvant représenter une plage de valeur plus grande que les précédents.

En C, vous pouvez accéder à ces types sous les noms uint8_t, uint16_t, uint32_t et uint64_t. Ils sont définis dans l'en-tête <stdint.h> (standard integers).

#include <stdint.h>

uint8_t entier_8_bits = 145; // maximum = 255
uint16_t entier_16_bits = 28493; // maximum = 65535
uint32_t entier_32_bits = 92837483; // maximum = 4294967295
uint64_t entier_64_bits = 374392373438ull; // maximum = 18446744073709551615ull

Comme vous pouvez le voir, selon les usages différents types d'entiers peuvent être utilisés. Dans la plupart des situations, les entiers 32 bits suffisent, mais si vous voulez compter la population mondiale vous aurez besoin de 64 bits car il y a plus de 4 milliards d'invididus sur Terre.

Vous noterez que ces valeurs maximales sont un peu ingrates à lire en décimal, mais beaucoup plus faciles à lire en hexadécimal :

• Le maximum d'un entier 08 bits est 0xff.
• Le maximum d'un entier 16 bits est 0xffff.
• Le maximum d'un entier 32 bits est 0xffffffff.
• Le maximum d'un entier 64 bits est 0xffffffffffffffff.

Si vous avez un nombre en hexadécimal il vous suffit donc de compter combien il a de chiffres pour savoir quels types entiers peuvent ou pas le représenter !


Entiers signés

Comme j'ai passé pas mal de temps sur les entiers déjà, je ne veux pas m'attarder ici. Mais sachez qu'il existe une technique pour représenter des nombres signés (positifs et négatifs) en binaire. On pourrait juste rajouter un bit pour dire si le signe est + ou -, mais c'est compliqué de calculer avec cette méthode. À la place, une technique appellée le complément à deux est utilisée presque partout.

La seule chose que vous avez besoin de savoir est que l'intervalle représentable par les entiers signés est réparti à moitié sur des nombres négatifs et sur des nombres positifs :

• Un entier signé sur 8 bits peut représenter de -128 à 127.
• Un entier signé sur 16 bits peut représenter de -32768 à 32767.
• Un entier signé sur 32 bits peut représenter de -2147483648 à 2147483647.
• Et ainsi de suite.

Ces types en C sont nommés int8_t, int16_t, int32_t et int64_t. Ils sont aussi accessibles dans <stdint.h>.

Vous remarquerez sans doute un schéma de nommage. u (unsigned) signifie que le nombre est non-signé, s'il n'y a pas de u on considère que le nombre est signé par défaut. int (integer) signifie « entier » en anglais, ensuite vous avez la taille en nombre de bits et le "_t" final est une convention pour dire que c'est un type (pour ne pas le confondre avec un nom de variable).


Une note sur les entiers standard : char, short, int et long

Vous ne connaissiez peut-être pas les types de <stdint.h>, et pensiez peut-être à des choses comme char, short, int ou long. Ce sont aussi des entiers, mais il n'est pas toujours facile de connaître leur taille.

Historiquement, int représente la taille d'entier préférée du processeur. Sur la calculatrice, qui utilise un SuperH 32-bits, c'est un entier de 32 bits. Mais sur le microcontrôleur qu'on trouve dans les Arduino, qui est un processeur 16 bits, c'est un entier de 16 bits. C'est d'ailleurs une erreur assez fourbe quand on programme sur une Arduino. Sur les EZ80 des calculatrices TI, qui est un processeur 8 bits, c'est un entier de 8 bits.

Quand les processeurs 64 bits sont arrivés, les gens ont jugé que peu de variables avaient besoin d'aller au-delà de la valeur limite sur 32 bits (plusieurs milliards !) et que ça ne valait pas le peine de doubler la mémoire que prennent les int juste pour ces cas-là. Du coup int est resté sur 32 bits, et c'est long qui représente les nombres de 64 bits. Mais tous les compilateurs et OS ne le font pas pareil... et du coup c'est juste un énorme bordel. Vous pouvez voir sur Wikipédia (en anglais) que selon le standard C, le type de processeur et l'OS utilisé la taille change, ce qui est vraiment pas pratique.

Mon conseil c'est de ne pas se casser la tête avec ça et :

• D'utiliser int quand on veut juste « un entier quelconque » et que la valeur maximale est de toute façon petite.
• D'utiliser les entiers de <stdint.h> quand on veut être sûr que l'entier peut représenter des grandes valeurs, ou qu'on veut un petit entier pour ne pas consommer trop de mémoire.


Le texte : ASCII et UTF-8, l'enfer passé sur les encodages

Profitons de cet instant pour faire un peu moins de maths et un peu plus de littérature. Comme toutes les choses qui existent dans le monde informatique, le texte est aussi représenté par des données binaires, et il faut donc un moyen d'associer une séquence de bits à une séquence de caractères.

Contrairement aux entiers où il y a beaucoup de contraintes (notamment celle que les additions et multiplications doivent être les plus efficaces possibles), pour le texte on peut faire un peu ce qu'on veut. Il suffit de choisir une séquence de bits pour chaque caractère qu'on veut pouvoir écrire, et tant qu'il n'y a pas d'ambiguïté ça marchera. On appelle ça un encodage de texte.

Dans les années 1960, les Américains ont inventé ASCII, un encodage qui dit quelle séquence de bits on associe à chacun de 128 caractères prédéfinis. Ce sont des caractères utilisés pour écrire du texte en anglais (évidemment), et c'est loin de convenir à tout le monde : il n'y a pas d'accents, pas d'alphabets non-latins, pas d'idéogrammes, et surtout pas d'emojis. À l'époque ça a fait un tôlée sur Twitter.

ASCII est tellement la norme de toutes les normes que même les super vieux encodages que vous pouvez trouver sont compatibles avec (c'est-à-dire que les caractères qu'ASCII couvre sont représentés dans ces encodages comme dans ASCII).

À l'origine ASCII utilise 7 bits par caractères, mais dans le monde moderne de l'octet on rajoute un zéro pour en avoir 8. Ainsi, en ASCII la séquence de bits pour la lettre "t" est 01110100, celle pour "e" est 01100101, et celle pour "s" est 01110011. On encode donc le mot « test » par

"test" 01110100 01100101 01110011 01110100

Mais c'est pas très lisible, donc comme d'habitude on utilise de l'hexadécimal.

"test" 74 65 73 74

Et si j'enregistre "test" dans un fichier, que j'affiche ensuite avec xxd, j'obtiens précisément cette séquence !

00000000: 7465 7374                                test

Retenez ASCII est un encodage fondamental utilisé pour l'alphabet latin et quelques caractères spéciaux, et absolument tout le monde s'y conforme.

C'est le bon moment pour revenir sur ce qu'affiche xxd dans sa troisième colonne. Pour rappel, voici le début de ce fichier affiché en hexadécimal :

00000000: 2320 5444 4d20 3138 203a 2043 6f6d 7072  # TDM 18 : Compr
00000010: 656e 6472 6520 6c65 7320 646f 6e6e c3a9  endre les donn..
00000020: 6573 2065 7420 6c65 7572 7320 7265 7072  es et leurs repr
00000030: c3a9 7365 6e74 6174 696f 6e73 0a0a 5b69  ..sentations..[i
00000040: 5d4c 6520 5475 746f 7269 656c 2064 7520  ]Le Tutoriel du
00000050: 4d65 7263 7265 6469 2028 5444 4d29 2065  Mercredi (TDM) e
00000060: 7374 2075 6e65 2069 64c3 a965 2070 726f  st une id..e pro
00000070: 706f 73c3 a965 2070 6172 205b 7072 6f66  pos..e par [prof
00000080: 696c 5d4e 6530 7475 785b 2f70 726f 6669  il]Ne0tux[/profi
(...)

Sur chaque ligne il y a 32 caractères hexadécimaux, ce qui fait 16 octets (8 groupes de 2 octets). La troisième colonne affiche les caractères ASCII associés à chacun de ces 16 octets lorsqu'il y en a, et des points sinon. On peut y voir plein de choses, par exemple que le premier octet (0x23) est le caractères "#", que les fins de lignes sont représentées par l'octet 0x0a, et que les accents s'affichent comme des points puisqu'il n'y a pas d'accents en ASCII.

(La première ligne affiche juste la position dans le fichier en hexa, vous pouvez voir que ça commence à 0 et que ça augmente de 0x10 = 16 octets à chaque ligne. Le préfixe 0x est implicite ici, c'est un peu casse-pieds quand on débute mais avec l'habitude on devine au contexte que c'est en hexadécimal.)

Le fait qu'il y ait si peu de caractères dans l'encodage ASCII fait qu'au fil du temps de nombreuses personnes et entreprises ont inventé leur propres encodages pour ajouter des caractères. Avec tous les pays du monde et la concurrence en plus, il existe une quantité faramineuse d'encodages tous plus incompatibles entre eux les uns que les autres, et cette variété a longtemps été un enfer parce qu'afficher un fichier utilisant un certain encodage avec un autre encodage donne un résultat incorrect et souvent n'importe quoi.

Par exemple, mon fichier est encodé en UTF-8. En UTF-8, le « é » de « données » est représenté, comme vous pouvez le voir à la fin de la deuxième ligne affichée par xxd, par les deux octets c3 a9. (Il y a bien plus de 256 caractères dans UTF-8 et donc tous ne peuvent pas s'écrire sur un seul octet.)

Si vous ouvrez ce fichier en pensant qu'il est encodé en ISO-8859-1, un encodage très courant en Europe avant qu'UTF-8 ne devienne la norme, vous obtiendrez un résultat très différent. Dans cet encodage, c3 est le caractère « Ã » et a9 est le caractère « © ». Du fait, vous verrez à votre écran, non pas « données », mais

« données »

Et je suis certain que ça vous est tous arrivé au moins une fois. C'est extrêmement casse-pieds et ça a posé des problèmes pendant des années, jusqu'à ce que Unicode débarque et commence à associer des nombres à tous les caractères utiles à l'époque, et mette tout le monde d'accord en écrasant tous les autres encodages avec un énorme pouvoir de standardisation.

(J'ai mentionné Unicode et UTF-8 : ce n'est pas exactement la même chose, mais dans le cadre de ce tuto on va considérer que c'est pareil sinon on sera encore là demain soir !)

Aujourd'hui, on est enfin sauvés et quasiment l'intégralité du monde utilise des chaînes de caractères et des fichiers en UTF-8, et ce problème est en passe de disparaître entièrement. Si vous avez déjà lu le manifesto sur le site utf8everywhere.org (en anglais) vous comprenez sans doute à quel point c'est important.

Retenez UTF-8 est le seul encodage dont le monde a besoin en 2020 et il n'y aucune raison d'utiliser autre chose.

Soit dit en passant, Casio se moque complètement de tout ça et continue d'utiliser dans son OS un encodage de texte personnalisé, que la communauté appelle FONTCHARACTER, qui semble vaguement dérivé de l'encodage japonais Shift-JIS en voie de disparition et qui vous oblige à écrire Print("donne\xe6\x0as") au lieu de Print("données"). (gint supporte l'UTF-8, je dis ça je dis rien. )

En C, le type char est utilisé pour représenter un caractère ASCII. C'est un type d'un octet, sur à peu près toutes les machines que vous pouvez imaginez c'est un entier signé sur 8 bits, la même chose donc que int8_t.

Vous pouvez désigner un caractère par son code ASCII, mais le langage C vous offre la possibilité de mettre un caractère entre deux apostrophes et le remplacera par la valeur correspondante.

char t = 0x74; // Le caractère "t"
char t = 't'; // Exactement pareil

Un char ne contient vraiment qu'un octet, donc si votre fichier source est encodé en UTF-8 (et il devrait l'être) vous ne pouvez pas écrire 'é' parce que ça prend deux octets (0xc3 suivi de 0xa9). Il y a des APIs standard pour faire ça en C (wide strings, multibyte) mais honnêtement c'est très casse-pieds à faire et j'espère que vous n'en aurez jamais besoin.

Une chaîne de caractères complète s'écrit entre guillemets et se termine par un octet de valeur zéro, qui indique la fin du texte (sinon on ne saurait pas où s'arrête la chaîne, ce qui est dommage). Par exemple, le mot "données" sera représenté en mémoire par la séquence d'octets :

"données" 64 6f 6e 6e c3 a9 73 00

Le type approprié pour obtenir ça est char * (si on oublie un instant les questions de lecture/écriture).

char *str = "données"; // en mémoire, la chaîne contient les 9 octets ci-dessus

Notez que le langage C n'impose pas un encodage, il prend vraiment les octets qui sont enregistrés entre les guillemets. Pour avoir du texte en UTF-8 dans votre programme il faut enregistrer votre fichier source en UTF-8.


Nombre flottants

En C, à peu près tous les types sont des entiers ou des pointeurs (on parlera de pointeurs dans le TDM 19). Les seuls autres types natifs sont les nombres flottants, un sujet qui mérite (et a) des livres entiers, et qu'on ne va pas du tout détailler ici.

Tout ce que vous avez besoin de savoir c'est que les nombres flottants permettent de représenter (plus ou moins bien) des nombres décimaux comme 0.25 et aussi des nombres extrêmement petits ou grands comme 0.5·10⁻⁸⁵ ou 2.7·10²⁴³. Après avoir été un bordel pendant longtemps (un peu comme le texte), les nombres flottants sont maintenant régis par l'IEEE 754, et il y en a principalement deux tailles :

• Les nombres flottants sur 32 bits (float en C), avec environ 6 décimales de précision
• Les nombres flottants sur 64 bits (double en C), avec environ 15 décimales de précision

Les deux marchent exactement pareil, tout ce qui change c'est que le double a plus de décimales et peut aller encore plus loin dans l'échelle du minuscule et du gigantesque.

Voilà qui conclut une présentation (somme toute rapide) des types de données qu'on manipule tous les jours dans les programmes et en particulier dans les add-ins.



Interprétation des données : pourquoi on type les variables et les fichiers

Avec tout ce qu'on a vu avant, pouvez-vous me dire maintenant ce que ces 4 octets sont ?

70 50 32 3f

Prenez le temps de réfléchir, voire même de relire les paragraphes précédents.

...

La bonne réponse est « non ». On ne peut pas dire ce que sont ces 4 octets, car on ne sait pas si ce sont :

• Les quatre caractères ASCII 0x70, 0x50, 0x32 et 0x3f, c'est-à-dire "p", "P", "2" et "?"
• L'entier non signé de 32 bits 1884303935
• Les deux entiers non signés de 16 bits 28752 et 12863
• Les quatre entiers signés de 8 bits 112, 80, 50, et 63
• Le nombre flottant de 32 bits 0.696540

Et c'est parce que toutes ces choses, dans la mémoire, sont représentées par les quatre octets 70 50 32 3f. Et c'est là un problème fondamental qu'il est important de toujours garder en tête :

Retenez Toute donnée n'est utilisable que si vous connaissez son type/format.

Le langage C vous oblige à indiquer le type de vos variables spécifiquement pour vous éviter de vous mélanger les pinceaux, et d'écrire un float quelque part dans la mémoire pour le relire plus tard comme un uint32_t par erreur. Parce que la mémoire s'en moque, elle vous donnera les octets, et votre programme continuera de fonctionner avec une valeur absurde.

Ce problème est encore plus important avec les fichiers. Autant vous pouvez avoir un float raisonnable dont les octets représentent également un int raisonnable, autant les octets d'une image PNG ne représenteront jamais une image JPG. Prendre l'un pour l'autre c'est un échec garanti.

C'est pour cette raison qu'on met des extensions sur les fichiers. Le image.jpg c'est un peu comme int n, c'est la combinaison d'un nom et d'un type, permettant à l'utilisateur de l'image (que ce soit un logiciel ou un humain) de savoir comment il faut lire et utiliser les octets du fichier.

Généralement les formats de fichiers sont encore plus prudents que ça et contiennent des signatures qui les identifient. Par exemple, les premiers octets d'un fichier PNG contiennent une signature qui utilise les trois caractères ASCII 0x50, 0x4e et 0x47 ("P", "N" et "G"). Et le premier octet, 0x89, est invalide à cette position à la fois en ASCII et en UTF-8, pour éviter que l'image soit prise par erreur pour un fichier texte. Le résultat c'est que quand vous avez en face de vous un fichier d'un type inconnu vous pouvez quand même détecter son type la plupart du temps (l'utilitaire file fait ça sous Linux).

00000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452  .PNG........IHDR
(...)

Les images sont des gros fichiers, généralement plusieurs milliers d'octets, donc on peut se permettre de consommer un peu de place pour mettre une signature. Mais dans un programme C où les variables sont des multitudes de petits objets, on n'a pas la place de noter leurs types en plus de leur valeur, et pas non plus le temps de vérifier à chaque utilisation que les types sont corrects. Il faut donc faire attention à ne pas lire des octets dans le mauvais type (ce qu'on appelle parfois du type punning).



Représentation des données : comment afficher ses variables

Maintenant qu'on a vu la différence entre les entiers et le texte, vous comprenez peut-être pourquoi il est impossible d'afficher un entier avec Print(), une fonction qui attend une chaîne de caractères.

En effet, si vous avec un int (de 4 octets) contenant la valeur 1729, ce que vous avez ce sont les quatre octets

00 00 06 c1

Mais pour afficher à l'écran vous avez besoin du texte "1729", qui contient les quatre caractères ASCII « 1 » (0x31), « 7 » (0x37), « 2 » (0x32) et « 9 » (0x39), plus un octet de valeur zéro à la fin pour signaler la fin de la chaîne. C'est-à-dire

31 37 32 39 00

Comme vous pouvez le voir c'est totalement différent. Non seulement ce ne sont pas les mêmes octets, mais en plus ce n'est même pas la même taille !

Obtenir le texte à partir de l'entier est donc une action non triviale qui requiert non seulement de décomposer le nombre en base 10 (ce qui nécessite de faire des multiplications et divisions par des puissances de 10) mais aussi de générer la bonne séquence de caractères ASCII. Ce genre de choses n'est pas automatique, et il faut bien que quelqu'un s'en charge.

Dans les langages plus haut niveau comme Python ou C++, la fonction print() ou l'opérateur << possèdent du code qui est appelé automatiquement si vous passez un entier en argument pour faire ce calcul. Mais en C, ce n'est pas automatique, et il faut utiliser une fonction de la famille de printf().

Il en va de même pour les flottants, en plus compliqué encore. Le problème avec les flottants c'est que contrairement aux entiers les nombres à virgule qu'on peut écrire en base 2 et en base 10 ne sont pas les mêmes. Et donc il y a des approximations et des ambiguïtés partout, et il faut faire excessivement attention tout le temps !



Conversions : ce qui en est et ce qui n'en est pas

Il y a beaucoup de vocabulaire dans cet article, et tous les termes n'ont pas forcément une définition spécifique, mais une chose est sûre : le terme « conversion » est souvent mal utilisé pour différentes raisons.

La question de la conversion vient du fait que les informations peuvent s'écrire de multiples façons. Par exemple, l'entier 1729 peut être écrit en binaire sur 16, 32 ou 64 bits (pas sur 8 car il est plus grand que 255). Il peut aussi être écrit sous forme du texte en base 10 "1729", du texte en base 16 "0x6c1", et bien d'autres façons encore.

Représentation ou encodage d'une information abstraite

Quand le sujet sur lequel on se concentre est une information abstraite, comme « l'entier 1729 », on dit généralement qu'on peut le représenter ou l'encoder dans différents formats. Les représentations de 1729 sont :

• Comme un nombre de 16 bits : 06 c1
• Comme un nombre de 32 bits : 00 00 06 c1
• Comme texte en base 10 : "1729" (dont les octets en ASCII sont 31 37 32 39 00)
• Comme texte en base 2 : "0b11011000001" (là je détaille pas les octets)
• Comme un nombre flottant sur 32 bits : 00 20 d8 44

De même, les encodages du mot « données » sont :

• En ASCII, rien du tout car l'ASCII ne peut pas représenter « é »
• En ISO-8859-1, 64 6f 6e 6e e9 65 73
• En UTF-8, 64 6f 6e 6e c3 a9 65 73

Retenez On représente une information par une séquence de bits.

Interprétation ou décodage d'une donnée

L'opération inverse consiste à prendre une donnée et à récupérer l'information abstraite. On parle d'interpréter ou de décoder la donnée. Comme on l'a vu, les interprétations de 70 50 32 3f sont :

• Comme texte ASCII, la séquence "pP2?"
• Comme entier non signé de 32 bits, 1884303935
• Comme nombre flottant de 32 bits, 0.696540
• (etc, il y en a bien d'autres)

Pour accéder à l'information il faut connaître le type de la donnée.

Retenez On interprète une séquence de bits pour récupérer l'information.

Conversion entre différents formats

Lorsque le sujet est une donnée (représentant une information) et qu'on veut obtenir une autre représentation de cette information, on peut parler de conversion de la donnée. Par exemple, l'information « entier 1729 » peut être représenté à la fois comme un entier 16 bis et comme un entier 32 bits, et la conversion du premier format au second transforme la donnée ainsi :

06 c1 → 00 00 06 c1

Les octets ont changé, on a donc converti la donnée tout en continuant de représenter la même information. De même, 1729 peut être représenté par un nombre flottant sur 32 bits, et la conversion d'entier 16 bits vers flottant 32 bits transforme la donnée ainsi :

06 c1 → 00 20 d8 44

Cette fois-ci la donnée n'a plus rien à voir mais l'information est préservée : c'est toujours 1729.

Comme ISO-8859-1 est un encodage vieux et que personne n'en veut plus, on veut convertir notre fichier texte contenant le mot « données » de l'encodage ISO-8859-1 à l'encodage UTF-8, qui est le seul encodage qui mérite encore d'exister en 2020. La donnée est transformée ainsi :

64 6f 6e 6e e9 65 73 → 64 6f 6e 6e c3 a9 65 73

Pas les mêmes bits, mais toujours le même mot.

C'est exactement pareil si vous convertissez une image BMP en PNG : pas le même fichier à la sortie, mais c'est la même image qu'avant. Vous voyez le motif ?

Retenez On convertit entre elles plusieurs représentations d'une même information.



Les conversions impossibles : ne pas se tromper sur le type

Même si ma définition reste heuristique, l'idée générale d'une conversion est de conserver l'information abstraite tout en changeant simplement le format qui la représente.

Mais cela n'est possible que si le format de départ et le format d'arrivée sont tous les deux capables de représenter l'information dont il est question. Par exemple, on ne peut pas convertir une image PNG en fichier texte, puisque l'information représentée par le fichier de départ (une image) n'est pas de même nature que l'information représentée par le fichier souhaite à l'arrivée (du texte).

De la même façon, on ne peut pas convertir un fichier g1a en fichier g1m car l'information dans le fichier de départ (du code exécutable et des données pour un add-in) n'est pas de même nature que ce que le fichier souhaité peut représenter (des fichiers résidant dans la mémoire principale).

Retenez On ne peut convertir des données que si elles représentent la même information.

De façon plus subtile, le terme de « conversion » a l'effet fourbe de nous faire croire qu'on peut transformer l'information dans les deux sens, alors que ce n'est pas toujours le cas.

Par exemple, si je réencode une image PNG au format JPG, la compression JPG va détruire une partie de l'information et ma nouvelle image sera subtilement différente de l'originale. Aucune transformation ne permettra de récupérer l'information perdue. Si on veut être vraiment rigoureux ce n'est donc qu'à moitié une conversion.

De la même façon, on peut convertir un nombre flottant en entier, mais on perd à la fois les décimales et la précision. Par exemple si j'écris int n = 1.47, le compilateur va automatiquement appeler du code pour convertir 1.47 (un double) en entier. Le résultat sera 1, et les décimales seront là aussi perdues.

Attention donc à ce que votre information devient quand vous planifiez de convertir une donnée !



Conclusion

Que ce soit dans les variables d'un programme ou dans les fichiers de votre ordinateur, des données de différents types se promènent partout dans le monde informatique.

Comprendre comment ces données sont écrites en binaire démontre pourquoi il est important de bien garder en tête quelle information on stocke et quelle représentation on utilise.

Une approche un peu rigoureuse du problème permet de mieux cerner les abus de notions intuitives comme celle de « conversion » et d'avoir un regard plus précis sur ce qu'on fait vraiment quand on manipule des données.


J'espère que ce (long) tutoriel vous aura appris quelque chose. J'ai pris beaucoup de plaisir à l'écrire, mais dans toute son imperfection il ne pourrait que profiter d'un commentaire ou d'une correction de votre part. N'hésite pas à en laisser dans les commentaires ! o/

Et à bientôt sur Planète Casio !

Consulter le TDM précédent : TDM 17 : Des images sur votre 90+E !
Consulter l'ensemble des TDM

Commentez cette news ! (8)

Publié par Lephenixnoir le

Voir toutes les news


Les publications de l'Avent 2020 - Programme des festivités


Bonjour à tous, visiteurs et membres habitués de Planète Casio !

Cette année, comme les années précédentes, je souhaitais organiser quelque chose pour l'Avent. En 2018 et en 2019 j'ai fait des puzzles, mais cette année il y a le concours de rentrée qui n'est pas encore terminé, et je pense que notre page d'accueil a besoin d'un peu d'attention plus que d'un événement.

Je souhaitais aussi organiser un week-end de test en Novembre mais les occasions étaient rares et le forum est relativement inactif en ce moment donc ça ne s'est pas fait.

Et donc cette année je vais changer de formule, et profiter de ce mois de Décembre pour publier un certain nombre d'articles que j'ai en tête depuis longtemps mais n'ai encore jamais eu ou pris le temps d'écrire. Cela inclut deux Press Shift pour vous proposer un peu du test que je n'ai pas pu organiser en Novembre.

Voici donc le programme des festivités !

TDM 18 : Comprendre les données et leurs représentations (2 Décembre)
• Press Shift #2 – Sword Burst Zero (Redeyes) (6 Décembre)
• Press Shift #3 – Terrario (KBD2) (11 Décembre)
• TDM 19 : Comprendre l'utilisation de la mémoire en C (16 Décembre)
• Une curiosité antique : magazine Casio 3"33 de Janvier 1994 (20 Décembre)
• Tutoriel d'utilisation de gint #3 : Des portes... beaucoup de portes. (23 Décembre)

Pour ceux qui ne connaissent pas toutes ces formules, voilà quelques détails.

• Les Tutoriels du Mercredi sont une série de tutoriels qui touche à de nombreux sujets, sans forcément avoir de fil conducteur, mais prend le temps d'aborder chaque question avec rigueur et qualité.
• Les Press Shift, un format inauguré récemment par Massena, sont des analyses et tests de jeux destinés à mettre en valeur les projets tout en discutant de conception de jeu vidéo.

Les tutoriels d'utilisation de gint me sont personnels ; j'en ai inclus un dans ce programme parce qu'ils prennent suffisamment de temps à rédiger pour que j'aie besoin d'un créneau organisé pour les écrire.

J'espère que vous apprécierez la lecture, et on se retrouve très bientôt pour le début des publications ! o/

Commentez cette news ! (6)

Publié par Lephenixnoir le

Voir toutes les news


Résultat du vote du Jeu de la rentrée 2020


Bonjour !
Après beaucoup de temps à cause de très peu de vote, nous nous retrouvons pour les résultats du vote du jeu de la rentrée ! parce que le jeu actuel date d'août, c'est pas terrible...


Pour dire, nous avons eu... 2 votes pour les 6 jeux présents, nous allons donc décortiquer ça pour avoir un article de qualité !
Rappelons tout d'abord les concourants :

- Fxgnuboy de Djpadbit est un émulateur de Game Boy pour calculatrices monochromes SH4, pouvant faire tourner des jeux jusqu'à 90 fps avec overlock !
- Game Of Life de CaptainLuigi est un simulateur de vie contrairement à ce que son titre laisse entendre où vous devrez survivre dans le monde hostile qu'est l'époque moderne...
- Jeu de la vie de Oskar est une adaptation du célèbre jeu de la vie de John Conway, adapté en Basic Casio.
- Jeu de la vie python de Oskar est exactement le même programme mais développé en python, pour Graph 90+E ou Graph 35+E II.
- Snake extension de Polsulpicien est une extension de son jeu de Snake !
- Space_War de Palpatine_78 est un add-in pour 90+E où vous incarnez un X-Wing devant tuer un maximum de chasseurs TIE (aussi vilains que les membres de TI-Planet). Arriverez-vous à tous les tuer ?
- Bêtes (demo) de Pedrobzh est une ébauche d'un jeu, ne disposant seulement que d'un menu pour le moment
- ChessLink de Darkjura est un jeu d'échec... multijoueur ! Pas sûr que les profs de maths apprécient cette invention

Il y avait de la matière ! Place au vote

On commence par un vote, mettant en haut de la liste Game Of Life, suivi de peu par Space_War... Et rien de bien impressionnant, nous arrivons avec un deuxième et dernier vote, mettant le programme de Djpadbit ex-æquo avec notre leader actuel.

Et... c'est la fin des votes... Pour récapituler après ce nombre TITANESQUE de vote, nous avons avec 3 points pour Game Of Life de CaptainLuigi avec Fxgnuboy de Djpadbit suivi de près par notre Space_War de Palpatine_78

Vous l'avez donc compris ! Aujourd'hui 2 gagnants !
CaptainLuigi et Djpadbit, vous avez le privilège de mettre ce magnifique trophée sur vos programmes !


[adimg=center]Trophee_JDM.png[/adimg]


Bravo à vous deux !

On se retrouve un jour peut-être pour une nouvelle élection du JDM, en espérant avoir plus de vote cette fois ci

Et surtout, joyeux confinement version 2
A bientôt sur Planète Casio !

Commentez cette news ! (3)

Publié par Tituya le

Voir toutes les news


Résultat du concours de rentrée 2020 - Défi Python de Xuanwu !


Salut, communauté ! On se retrouve aujourd'hui pour analyser et classer les participations à notre Défi Python de Xuanwu, le premier défi de du concours de rentrée 2020 !

Nous avons reçu 154 participations de 28 personnes, le plus grand nombre de personnes individuelles et second plus grand nombre de participations toutes éditions confondues. Là-dedans, 6 personnes se sont placées dans la guilde Planète Casio et 16 dans la guilde TI-Planet. Merci à tous ! o/


L'objectif de cette épreuve était de parcourir un labyrinthe en consommant le minimum d'énergie à l'aide d'un véhicule programmable. Les modalités ont été détaillées par Hackcell dans un topic d'entraide si vous voulez voir les détails ; les principaux éléments sont les suivants :

• Les contrôles disponibles sont de la forme avancer, tourner à gauche et tourner à droite.
• Il y a un coût fixe pour chaque action.
• Il y a aussi un coût sur le nombre de décimales des valeur spécifiées : avancer(1.3937) coûte plus cher que avancer(1.4).
• Il y avait plusieurs chemins et les chemins plus longs recevaient un petit bonus pour équilibrer.

Voyons voir ce que vous avez réussi à trouver avec ces règles ! Nous avons rédigé quelques commentaires pour chacune de vos participations, n'hésitez pas à ajouter des détails sensationnels et autres techniques secrètes dans les commentaires.


Le classement

26. KikooDX () : 320011.24538193 (Programme : x37.py)

Notre première participation est de bien des façons également la meilleure. Voyez-vous, il y a un secret dans ce labyrinthe. Si vous tournez de 2⁹ radians vers la droite tout en avançant de 1337 pas entre chaque rotation, vous serez emmené·e tout droite à la sortie ! Définitivement la méthode la plus élégante !

Au fond cette technique reflète bien l'usage quotidien des calculatrices de niveau Lexibook, et ça se voit puisque le score final s'approche du rapport prix/qualité de la machine. x3



25. Anonyte () : 161.84356628353 (Programme : x18.py)

La participation suivante nous vient d'Anonyte. Personne n'a eu de mal à situer, vu le calcul du score, que les chemins ayant le moins de segments seraient les moins chers à autres facteurs égaux. On attaque donc avec un chemin de longueur 11, des angles et longueurs ajustés à la main - les angles au dixième, parfois au centième.

Ce score de 161 représente une amélioration de 99.949% par rapport à la participation précédente, la plus grosse séparation de toute l'épreuve.



24. OulanB () : 138.59776036691 (Programme : x38.py)

En ajustant les longueurs au dixième également, OulanB évite les collisions avec les murs, qui sont lourdement pénalisées sur le score. On gagne immédiatement 23 points sur le résultat. Dans l'ensemble tout le monde a fait attention à ne pas croiser les murs quitte à s'arrêter au milieu des couloirs.



23. Arm234 () : 132.33617133049 (Programme : x84.py)

Le programme d'Arm234 est le premier à utiliser un chemin de 10 segments. Les longueurs sont ajustées au centième, ce qui ajoute entre 10 et 20 points, mais l'économie d'un segment (une orientiation à 5 points et un mouvement à 8 points, plus les décimales) permet de compenser. Ce qui montre bien que la première étape devait être de trouver le chemin le plus court sans se soucier du calcul des décimales.



22. M4x1m3 () : 105.42754591515 (Programme : x20.py)

Ce parcours de M4x1m3 est certainement le plus tordu de toutes les soumissions ! Malgré un bon détour, il atteint un score de 105 points. J'admets ne pas être certain de comment il en arrive là.



21. Robin M. : 104.18973099423 (Programme : x107.py)

Le chemin emprunté par Robin M. est le seul à passer par la ligne supérieure. C'est un passage que j'avais envisagé en ajoutant le bonus pour les chemins plus longs. Il n'est pas très compétitif (malheureusement ce problème laisse peu d'espace aux variations sur le chemin), mais ça reste une bonne approche qui s'avance très près de la barre de 100 points.



20. Darks () : 91.41917680793 (Programme : x52.py)

Avec Dark Storm on arrive au point du classement où tout le monde utilise la même technique de sortie. Ce zig-zag final permet d'éviter des tours et cache encore une surprise que le top 13 a su s'approprier. C'est aussi la dernière participation à 10 segments et la première en-dessous de 100 points. Le point d'équilibre parfait !



19. CaptainLuigi () : 81.601629520489 (Programme : x146.py)

C'est ce chemin qu'on découvre avec CaptainLuigi, à 9 segments, qui est utilisé par le plus de participants : 10 en tout. On est tout juste avant la limite de 80 de score et l'optimisation s'apprête à descendre dans les fins détails de distance, de décimales sur les angles, et de décimales sur le score.



18. bebertii () : 76.379566366772 (Programme : x123.py)

Avec le même chemin que le CaptainLuigi, mais 4 décimales de moins dans la spécification des angles et des longueurs, bebertii inaugure la catégorie 70-79 de score, qui est la dizaine finale. Aucun chemin soumis ne produisait un score en-dessous de 72 (décimales non comprises). De là à vous dire si c'est possible ou non... je vous laisse émettre les hypothèses.



17. Afyu () : 76.000906078003 (Programme : x64.py)

Ce chemin est l'alternative à 9 segments. La plupart des meilleurs scores se sont battus entre cette version et celle des deux soumissions précédentes. La différence n'est pas énorme, mais c'est intéressant de voir alterner les formes au fur et à mesure qu'on monte en score. J'ai tenté d'équilibrer le score pour qu'il y ait plus d'un chemin optimal mais ce sont les deux qui tiennent la compétition.

Si vous avez regardé le code de génération, c'est ce que Wikipédia appelle le fusion aléatoire de chemins sauf qu'on continue de retirer des murs une fois le labyrinthe connexe, justement pour qu'il y ait plus de solutions.

Afyu nous a même donné une explication de sa méthode.

Afyu a écrit :
Effectivement, j'ai tout fait moi même, mais sans décortiquer le script, donc j'ai raté l'astuce des angles à une seule décimale.
Pendant mes recherches, au début, j'ai choisi des arrondis, mais pas forcément au dixième

distance[a]=int(100*distance[a]+1)/100

simplement parce que l'écriture avec un grand nombre de 9 après la virgule (dû à la méthode de calcul en binaire des ordi) des nombres déterminés par mon algorithme me dérangeait "esthétiquement".
J'ai effectivement le "bon" chemin (aux ajustements d'angles et de distances près) et j'ai également longuement travaillé sur le chemin finalement également choisi par Pavel. J'avais trouvé l'astuce de mettre une dernière distance hors bornes pour améliorer le score, mais ça n'a pas suffi.
(message original)



16. Dubs () : 74.750056119786 (Programme : x139.py)

La participation de Dubs est la seule rendue sur HP Prime. Pour rappel, le calcul des collisions et du score est fait purement formellement, et n'est pas impacté par l'affichage. Donc la notation est indépendante du modèle (sauf cas pathologiques de résultats de calcul en flottant). Notez qu'on revient au premier chemin de 9 segments.



15. cent20 () : 73.04042664132 (Programme : x102.py)

Alors qu'on se rapproche de la barre fatidique des 72, on repasse sur le chemin alternatif de 9 segments. À ce stade tout le monde limite au maximum l'utilisation des décimales, que les solutions soient optimisées à la main ou pas.

L'idée de compter les décimales vous surprendra peut-être. L'intuition c'est que si on autorise des nombres quelconques sans pénalité, il devient beaucoup plus facile, une fois qu'on a une idée générale du chemin à prendre, de calculer les angles et les longueurs qui optimisent la distance parcourue, le total d'angle parcouru, ou à peu près n'importe quelle métrique de votre choix.

De façon générale, les problèmes sur les réels sont plus faciles que les problèmes sur les entiers. Cette contrainte visait à vous empêcher de calculer les optimaux avec un programme en trois clics. Même si, vous le verrez à la fin du classement, ça s'est retourné contre moi puisque la pénalité était trop forte et du coup le nombre de valeurs viables (à 0.1 près) était faible, ce qui a permis à certains candidats de faire du brute-force.



14. grandben49 () : 73.003909873986 (Programme : x137.py)

Vous remarquerez que tout le monde ne fait pas le zig-zag final de la même façon. Certains le prennent de façon plus serrée, comme grandben49, alors que d'autres en font des paquets pour faire le long aller-retour possible. Ça vient du bonus attribué aux chemins les plus longs. Il n'y a de coût que pour utiliser les fonctions et spécifier des décimales. Une fois le nombre de segments fixé, c'est plus rentable de parcourir le plus de longueur possible pour minimiser le score.



13. Ne0tuX () : 72.747717453626 (Programme : x150.py)

Ne0tux est le premier dans ce classement à avoir utilisé le bonus de longueur (qu'il a remarqué de justesse) lors de la sortie du labyrinthe. Voyez-vous, pour une raison complètement intentionnelle que j'avais absolument prévue et validée durant les tests, le programme continue de vous faire avancer une fois que vous avez passé la sortie.

Du coup, si vous prenez un angle rasant pour sortir du labyrinthe le plus à l'horizontal possible, le chemin peut se prolonger sur un bon paquet de cases avant d'atteindre le mur fixé en bas de l'écran. Tout ce parcours supplémentaire s'ajoutant bien entendu au bonus de longueur, ce qui permet de réduire le score final.

Bravo à tous ceux qui s'en sont rendus compte à la lecture du code.

Ne0tux a écrit :
J'ai procédé de façon un peu originale ; une réminiscence des défis de dessin des années précédentes. J'ai commencé par lire le code puis confirmer certaines intuitions via la GUI de Pavel. Puis j'ai téléchargé le code sur mon smartphone et imprimé le labyrinthe sur papier, avant de partir pour 15 jours de congés sans PC ni Wifi. Avec mon bout de papier, une règle, un rapporteur et la volonté de faire un nombre minimal de traits les plus longs possibles et passant par le centre des "portes", j'ai pu tracer une sorte de "couloir des possibles".

J'en ai testé plusieurs sur smartphone (sans GUI) et validant ma solution finale via la version Oméga en ligne. Comme comparer était fastidieux depuis mon petit écran, je n'ai pas cherché plus loin que le 1e digit pour la rotation (ça tombe bien, il fallait le moins de digit possible). Sauf sur l'un des premiers points, ce qui explique que je sois resté à 72. Pour la longueur des segments c'était moins drôle car la mesure sur mon papier ne correspondait pas : souvent on pouvait approcher un mur, augmenter la longueur et quand même diminuer le score. J'ai bien faillit ne pas le voir !

La seule "optimisation" scriptée pour moi concernait la longueur et l'orientation des deux derniers segments, pour aller chercher un x en dehors du labyrinthe le plus loin possible.
(message original)



12. jacobly () : 71.056893450111 (Programme : x31.py)

Une autre participation qui se démarque est celle de jacobly, qui n'utilise... que des entiers. Vous avez bien entendu : un peu d'imagination, une bonne heure de recherche et une calculatrice lui ont visiblement suffit pour passer sous la barre des 72. Je vous cache pas que je m'y attendais pas à celle-là.

jacobly a écrit :
Not much to say about my method, just spent about an hour finding the shortest path with the original program, and couldn't be bothered optimizing floating-point error for the update.
(message original)



11. Filoji () : 71.018891561397 (Programme : x96.py)

Certains de ces commentaires sont très complets donc je vous laisse avec les explications.

Filoji a écrit :
1 - Découverte
C'était la catastrophe, entre le topic d'entraide et les calculs incompréhensibles, je me disais que c'était peine perdue... Mais j'ai persévéré, et ai trouvé enfin le premier chemin ! (142 pts)
Bon, après j'ai continué et j'ai trouvé mieux (120 pts)

2 - Le sub 100
Je rejoins PC et Casio pour avoir la meilleur équipe (Parce que Lexibook )
Grâce à Bzh, j'ai trouvé le bon chemin (Il avait fait ça à l'arrache sur Gimp), et je trouve mes 1ers sub 100 !!! (88 pts)
Ensuite, Pavel nous partage son outil pour améliorer notre score, et je m’améliore encore (75 pts, 72 pts)

3 - La course aux décimales
C'est bon, j'ai compris la technique... Mais quelques heures trop tard !
J'arrive ex aequo avec toute les personnes de ce rang, et je cherche alors à faire le moins augmenter mon score pour pouvoir trouver un score unique
Ça y est, j'ai trouvé, Merci Pavel, j'ai séché ton programme pour enfin trouver les 71,01889156139690 et les 200 unités de déplacement pour optimiser le plus ma consommation

Fin, voilà, c'est pas extraordinaire, mais c'est moi qui l'ai fait
(message original)



10. TIny_Hacker () : 71.000399584431 (Programme : x151.py)

Pas mal de gens ont utilisé l'interface graphique de Pavel pour faire leurs tests. Critor et moi avions une version SDL2 de polycalc.py pour tester rapidement sur PC (... même si Critor a enduré la mise en compatibilité avec tous les modèles), mais Pavel a carrément créé un outil interactif pour explorer le labyrinthe. Alors tout de suite les scores sont descendus pas mal.

Voilà une image de l'explorateur interactif de Pavel, puis l'explication de TIny_Hacker.


TIny_Hacker a écrit :
Honestly, I only did this well because of Pavel's GUI, which allowed me to test my ideas faster than manually typing them out, and to tweak things as I went. I started by figuring out on paper what path had the fewest number of segments and went from there. Eventually, I discovered that shortening the decimal on turns would decrease the score, and finally that adding a 0.000049999 (or something like that) could decrease the score without changing the path itself. Afterward, I just messed around till I got as low of a score as I could. That's about all there was to it!
(message original)



9. dvon () : 71.000243500836 (Programme : x152.py)

Pour sa part, dvon a utilisé un algorithme aléatoire, visiblement en déplaçant au hasard les angles de quasi-multiples de 2π le long du chemin pour obtenir un meilleur score. Le sujet imposait des limitations pour éviter ce genre de méthode, bravo pour les avoir contournées !

Cette participation est la première à utiliser des variations d'angle et de distance inférieures à 10⁻⁵. En effet, à cause de différences de calcul d'une machine à l'autre, il a fallu faire pas mal de compromis sur l'évaluation du nombre de décimales. Un de ces compromis était d'arrondir à 5 chiffres après la virgule... ce que les participants observateurs se sont empressés d'utiliser à leur avantage.

dvon a écrit :
For my solution, I started with the GUI shared by Pavel. I added code to try to automatically tweak argument values to get lower scores. But this didn't help, because (as I figured out eventually) the best scores were always from the values with only one digit after the decimal point.

In the end I used a version of the GUI modified just a little bit. I added code to output a record of scores for everything I tried a long a path, so that I could make sure I was doing at least as well in the current attempt as in previous attempts, and I made it possible to tweak angle and distance arguments by +-0.000004 units (and not round
the tweak away), since this slight difference wouldn't affect the part of the score based on the number of characters needed to represent the value. Also, for each turn I experimented with adding or subtracting a full rotation (i.e., about 2pi but not exactly because of the 1/10 increments) and was able to avoid using any angles that would be treated as 4-character values in that part of the scoring.
(message original)



8. Ruadh () : 71.000066133741 (Programme : x112.py)

Déjà top 8, et on arrive sur la première optimisation à coup de sinus. Un des problèmes des toutes premières versions du script c'est que seul le coût des déplacements était pris en compte. Ce coût est entier, il n'y a donc rien à exploiter entre 71 et 72... ce qui aurait fait beaucoup trop d'égalités.

Du coup j'ai proposé de faire la modification arbitraire d'ajouter au score le sinus de la somme des longueurs et angles utilisés durant le parcours. C'est fourbe parce que comme les participations sont limitées à peu de décimales, il n'est pas facile d'atteindre les valeurs minimales du sinus, qui se situent sur des demi-multiples de π. Par chance, 11 est presque égal à 3.5π donc il était possible d'avoir un sinus de presque -1 et donc d'arriver à presque 71.

Ruadh a écrit :
En lisant le programme, j'ai pu apprendre qu'il fallait :
- minimiser le nombre de virages
- ne pas foncer dans les murs
- parcourir une distance d'au moins 200
- utiliser des distances et angles avec au plus une décimale

J'ai donc cherché manuellement un chemin qui respecte toutes ces propriétés et j'ai obtenu un score aux alentours de 72. J'ai ensuite remplacé certaines rotations afin de minimiser le sinus (tourner à gauche de α revient à tourner à droite de -α) et j'ai obtenu le score 71,00001411857056 que beaucoup de personnes avaient déjà obtenu. J'ai donc à nouveau modifié les rotations pour avoir un score plus élevé.
(message original)



7. Alice () : 71.000014118571 (Programme : x88.py)

Hackcell résume superbement l'intégralité des règles et techniques utilisées jusqu'ici.

Hackcell a écrit :
Alors, j'ai vraiment procédé étape:

- Premier jet à la R.A.C.H.E (iso-1664) qui me donne dans les 150 points
-Lecture du code et écriture d'un topic sur ce dernier, je me rend donc compte qu'il faut minimisé le nombre de virage et maximiser la distance (dans la limite des 200 unité arbitraire)
- j'obtient donc un score d'environ 93.
- je me rends compte que l'on peut continuer une fois sortit du labyrhinte, ce qui facilite la maximisation de la distance, je descend a un score de ~83 (si continuer ainsi n'avais pas été possible, l'epreuve aurait sans doute été beaucoup plus challenging, mais c'etait fun quand même)
- grâce a ma connaissance du code, je me rends compte que le seul moyen de descendre c'est de supprimé un virage ou faire disparaitre les décimales. Or le meilleur score actuel est de 72 ce qui correspond au score que j'obtiendrait si j. supprimais ces decimales, je recherche donc de ce cotés, et bingo, 77, puis le fameux 72.
- enfin presque, entre temps il y a une régles en plus, on reçoit des points en fonction du sinus d'une fonction assez simple a manipuler, le seul probléme c'est que pour supprimé les décimales on se retrouve a se balader de 0.1 en 0.1 sur cette fonction, ce qui n'est pas l'idéal pour la minimiser, je test donc plusieur valeurs , change des virages a droite de theta par des a gauche de -theta, tente de continuer aprés la sortie pour explorer cette fonction en restant dans les conditions optimales (9 virages, pas plus d'une décimale) et finis avec un 71,000…
Je décide alor de m'arreter là jusqu'a ce qu'un score qui signifirais 8 virages soit trouvé, ce qui n'est pas arrivé.
(message original)



6. Ti64CLi++ () : 71.000013644375 (Programme : x153.py)

Malgré l'utilisation d'un bon vieux sinus pour tenter de faire sortir des scores différents à tout le monde, Ti64CLi++ s'est retrouvé plusieurs dans la situation de devoir ajuster ses scores pour éviter de créer des égalités (qui étaient interdites). Les plus rapides y trouvent leur compte... cela dit je veut bien donner un cookie à qui saura produire une égalité sur le défi du Léviathan sans se concerter !

Ti64CLi++ a écrit :
Alors, j'ai vraiment tout fais à la main.

J'ai commencé par tester le programme et voir quel score je pouvais obtenir comme premier jet, et c'est ainsi que j'ai envoyé mon premier score de 148.

Ensuite, j'ai vite compris que moins il y avait de segment, et plus ceux-ci étaient long tout en minimisant le chemin, meilleur le score était. Après plusieurs essais, j'ai donc obtenu les scores de 133 puis 99 puis 80. Entre temps, j'ai du donc changé de chemin pour descendre à 9 segments.

Là j'ai commencé à bloqué, puis une première lecture du code m'a permise de me rendre compte que les chiffres significatifs jouaient un rôle important dans le calcul du score. J'ai donc cherché un moyen de passer à un unique chiffre après la virgule. J'ai ainsi baissé mon score à 74 puis 73 puis 72.

Encore une fois, j'ai un peu galéré, mais après 1h de différents tests sur le même chemin, j'ai enfin passé la barre fatidique des 72. Il restait encore quelques améliorations à faire, mais après quelques changements minimes, je suis arrivé à mon score de 71.000014.
Tout ça pour me rendre compte plus tard dans la journée après mise à jour des participation, que Tituya avait envoyé le même score quelques 40 minutes plus tôt.
J'ai donc baissé mon score du minimum que je pouvais, et j'ai envoyé mon 71.00554.

Je suis resté sur ce score jusqu'à ce que _iPhoenix_ descende en dessous de moi, et me propose de m'aider si vraiment je coince. Il me dit donc de regarder attentivement la fonction cout, à laquelle je n'avais pas vraiment fait gaffe.
Après quelques réflexions et tests avec Python, je me suis aperçu que je pouvais encore baisser mon score en jouant sur les chiffres à 5 ou plus positions de la virgule à droite.
J'ai donc aisément réussi à baisser mon score en appliquant cette technique et j'ai obtenu 71.0000139, parce que comme un débile je n'ai appliqué ça qu'aux distances et non aux angles. Tout ça pour me rendre compte que, encore une fois, Tituya, n'avait lui pas fait cette erreur, et par la suite avais soumis un score de 71.0000136.

Enfin, quelques heures (pratiquement 2h tout pile) avant la fin du concours, j'ai retrouvé un peu de motivation, et me suis donc assuré la 6ème place en appliquant cette fois-ci la méthode aux angles. J'ai donc envoyé mon score de 71.00001364437452.
(message original)



5. Tituya () : 71.000013644375 (Programme : x141.py)

Le top 5 est excessivement complet dans ses explications, donc je leur laisse la parole !

Tituya a écrit :
On commence doucement avec une première tentative à 152. Ce score a bien chuté depuis



À la toute première approche je n'ai absolument rien testé de précis, j'essaye simplement de voir à la main ce que je peux produire et comment contrôler cette machine mystique.

Un peu de lecture, ça ne fait pas de mal :

Je comprends cependant très vite que nous devons améliorer le nombre de virages pour changer la valeur du score. Je remarque en même temps que l'instruction a_gauche semble être plus rentable que sa compère a_droite.
Et en effet, cela me permet bien de diminuer mon score.

Je continue ma lecture du code. Nous avons une distance maximale possible de 200. Qui donne un bonus considérable sur le score final, il faut donc maximiser celui-ci !

L'art du bourrinage :

Dans une envie soudaine, je programme un code de bruteforce me permettant de trouver théoriquement le meilleur score possible. Je me rends vite compte que la vitesse de python et le nombre de calculs à faire rend juste impossible cette procédure

Je lance quand même ce script pour optimiser les 3 premiers virages. Qui me donne des résultats plus que corrects !
Je lance ainsi de suite des optimisations grâce à ce script d'une succession de virages. Ce qui m'amène à ce fameux score assez commun de 71,00001411857056

Puis je bloque.

Je pars en freestyle pour voir ce que ça donne :

Mais au bout d'un moment je me demande si je ne peux pas rajouter des 0 ou des 9 un peu partout sans aucune logique peut me permettre de descendre.
Dans ma tête, le principe est simple :
Il faut limiter au maximum la distance totale tout en gardant le score[6] à 200.

J'essaye, ça marche correctement... Super !

Puis j'essaye des valeurs de plus en plus précise pour voir si ça change quelque chose, je me rends compte qu'en dessous de x.x99995, mon score descend.
J'optimise donc à la main chaque virages pour enfin arriver à mon score final : 71,00001364437450

Des tentatives théoriques

À partir de là, un peu de théorique. La précision des virgules est géré par le total (virage + distance). Je calcule alors ce que je dois enlever pour obtenir un score maximal.

Je n'ai cependant jamais réussi à trouver ce score... Peut-être qu'il est d'ailleurs impossible à avoir
Donc j'arrive avec ce magnifique score qui me donne la chance d'être 5e dans ce concours !
(message original)



4. LeGmask () : 71.000009639162 (Programme : x149.py)

LeGmask a écrit :
Spoiler: j'ai tout fait a la main
Dans les faits la plupart de mes outils mon fait perdre plus de temps qu'autre chose, après nombreuse tentative je suis descendu a 100 et des brouettes et y suis resté bon nombre de temps, j'ai fini par craquée et est demandée des indices a _iPhoenix_
C’est là que le massacre commence, de 1 j’avais pas le bon chemin, et de 2 j’avais des angles a 2 décimales …

Après quelque heure de recherche je finis finalement par descendre a 71,…14… sauf que spoiler, vu que je m’y suis pris encore une fois 3 mois après la course, le score était pris :notlikethis:
À ce point obligé de détériorer mon score afin de publier pour la première fois mon résultat.

Le cours de philo qui suit ne ma pas porter conseille et encore une fois _iPhoenix_ ma sauvée la mise avec un précieux indice, j’avais compris le code de l’arrondis, mais pas totalement vu que je n’avais pas pensée au tout petit décimal qui pourrait optimiser le tout encore plus 😊

Finalement je descends et me place en 6e position, là j’ai beau essayée tout ce que je peux je ne comprends pas, comment descendre beaucoup plus, puis encore une fois un indice sur le sinus par _iPhoenix_ ma remis sur le pied de guerre, j’ai donc cherché et vu qu’on pouvait descendre sur le sinus de 11 beaucoup plus proche de -1, la avec les décimaux j’ai pu descendre mon score et me placer 4e
Dans tous les cas je remercie grandement _iPhoenix_ pour tous ces petits conseils, sans lui je ne saurais sans doute pas là, et je reste une grande arnaque 😊.
(message original)



3. _iPhoenix_ () : 71.000009399186 (Programme : x134.py)

_iPhoenix_ a écrit :
After getting the opencv2 script from commandblockguy, I tried getting a path that worked, not thinking too much about scoring- I ended up with a score that was around 470 or so, not so great: (click any image to enlarge)


After realizing that turning and moving had a fixed cost in addition to their distance, I tried to reduce the number of segments:




This got me to around 86 or so. (One interesting trick I employed was lengthening the last segment out of bounds)

This all happened within an hour or so of me having the code, so I didn't really write or use any tools at this point- there was no need.

I eventually wrote a function that would let me give it points- this took me longer than I would care to admit (my trig is quite rusty). Here it is, in all of its glory:

def move_to(x, y):
  cur_x, cur_y, cur_angle = state[0:3]
  a_gauche(round(cur_angle - atan2((y - cur_y), (x - cur_x)), 1))
  avancer(round(sqrt((x - cur_x) ** 2 + (y - cur_y) ** 2), 1))

I modified the functions for turning and for moving so they would dump code I could submit into a file- this was a really simple change and was extremely convenient.

For brute-forcing, I just defined a noise function that was easy for me to tweak (for example, changing it to a Gaussian distribution or tweaking the parameters). I mostly used brute-forcing to eliminate decimal places.

def noise():
  return (random() - 0.5)/10

Throughout this process, commandblockguy was extremely helpful. I did feel a little guilty asking for help, but I made sure to at least drop hints to anyone who asked me in return (which ended up being a decent number of people)
(message original)



2. Pavel () : 71.000009399186 (Programme : x86.py)

Pavel a écrit :
Voici une explication de mon approche pour trouver une solution à ce défi.

J'ai commencé par essayer de comprendre comment la consommation est calculée. Voici les parties du code Python montrant tous les composants des calculs de consommation:

def fix_angle(a):
  return a * 2 * asin(1) / pi

def a_gauche(a):
  global state
  state[7] += a
  state[5] += 5 + cout(a)

def avancer(l):
  global state
  state[7] += l
  state[5] += 8 + cout(l)
  while(l > 0):
    l -= .25
    state[6] += (state[6] < 200)

def aller_selon(f):
  global state
  state = [0, .5, 0, 0, .5, 0, 0, 0]
  f()
  state[5] += sin(fix_angle(state[7])) - state[6] // 2
  print('Consommation : ' + str(state[5]))

Apparemment, la consommation se compose des trois éléments suivants:

state[5] = consommation de base
state[6] = distance totale parcourue multipliée par quatre
state[7] = angle total + distance totale

Ensuite, j'ai testé la fonction 'cout()' qui est utilisée dans les calculs de consommation:

>>> from laby import *
>>> cout(5)
3
>>> cout(0.5)
3
>>> cout(0.05)
4
>>> cout(5e-3)
5
>>> cout(5e-4)
6
>>> cout(5e-5)
7
>>> cout(5e-6)
3

Il semble donc que la consommation puisse être minimisée en combinant les éléments suivants:

• minimiser la quantité de manoeuvres
• minimiser 'sin(state[7])'
• maximiser la distance totale parcourue
• ne pas utiliser plus d'un chiffre décimal après la virgule décimale
• essayer d'exploiter le faible coût du 'cout(5e-6)'

Pour minimiser 'sin(state[7])', j'ai utilisé le code Python suivant pour créer un tableau montrant les valeurs de la fonction 'sin()' pour différents angles avec un seul chiffre décimal après la virgule décimale:

from math import pi, sin

l = []

for i in range(-10, 11):
  a = round(-pi/2 + 2 * pi * i, 1)
  l.append((a, sin(a)))

l.sort(key=lambda e: e[1])

for e in l:
  print('a = %5.1f -> sin(a) = %f' % e)

Voici le résultat:

a = -64.4 -> sin(a) = -0.999996
a = -26.7 -> sin(a) = -0.999994
a =  11.0 -> sin(a) = -0.999990
a =  48.7 -> sin(a) = -0.999986
a =  42.4 -> sin(a) = -0.999934

De petites valeurs de 'state[7]' sont donc nécessaires pour une faible consommation. Vu que 'state[7]' est la somme des angles et des distances et que les distances ne peuvent pas être négatives, alors les valeurs des angles passés à la fonction 'a_gauche()' doivent être négatives.

Une fois que tout ça est devenu plus ou moins clair, j'ai modifié le code laby.py pour en faire une version qui peut être contrôlée comme un jeu vidéo avec les touches haut/bas/gauche/droite sur le clavier: https://gitea.planet-casio.com/Pavel/labygui

En utilisant cette approche, j'ai obtenu la solution suivante:

from laby import *

def chemin():
  for e in [(-6.6, 2.3), (-7.3, 6.3), (-5.2, 4.6), (-4.8, 4.1), (-7.3, 6.3), (-8.3, 3.8), (-5.1, 3.8), (-2.3, 4.3), (9.1, 13.3)]:
    a_gauche(e[0])
    avancer(e[1])

aller_selon(chemin)

La consommation correspondant à cette solution est de 71.0000097934493.

À ce stade, je n'ai toujours pas exploité le faible coût du 'cout(5e-6)'. J'ai donc essayé d'ajouter ou de soustraire 5e-6 des distances et des angles. La solution qui m'a donné le score le plus bas (71.00000939918644) était la suivante:

from laby import *

def chemin():
  for e in [(-6.6, 2.3), (-7.3, 6.3), (-5.2, 4.6), (-4.8, 4.1), (-7.3, 6.3), (-8.3, 3.8), (-5.1, 3.8), (-2.3, 4.3), (9.1, 13.3)]:
    a_gauche(e[0] - 5e-6)
    avancer(e[1] - 5e-6)

aller_selon(chemin)

Au moment où j'ai trouvé cette solution, elle était déjà soumise par commandblockguy et j'ai dû trouver la deuxième meilleure solution (71.00000939918645) en ajoutant de très petites valeurs aux angles et aux distances:

from laby import *

def chemin():
  for e in [(-6.6, 2.3), (-7.3, 6.3), (-5.2, 4.6), (-4.8, 4.1), (-7.3, 6.3), (-8.3, 3.8), (-5.1, 3.8), (-2.3, 4.3), (9.1, 13.3)]:
    a_gauche(e[0] - 5e-6 + 1e-13)
    avancer(e[1] - 5e-6 + 1e-13)

aller_selon(chemin)
(message original)



1. commandblockguy () : 71.000009399186 (Programme : x75.py)

commandblockguy a écrit :
As for my strategy, I basically found a path through the maze by hand that had as few points as possible, without worrying about my score too much. I made sure to take a very shallow angle when exiting so that the path would be long enough to get the maximum score.

I then tested every single combination of angles and distances that would put me within some distance (if I remember correctly, about 1.5 tiles, though I changed it several times) of my original points, while still allowing me to get the maximum score. This was feasible because you get points off for each digit after the first decimal place, or before the units place, which means that there are only 100 angles and 100 distances to try for each point. The exception for this is the last point, which has to be more than 10 units away in order to meet the length requirement. This took a few hours to run in its entirety, and I was left with a few thousand paths. Prior to the scoring change, all of these paths would have left me with a score of 72, but after the scoring change it was now possible to get a fractional score.


A "heatmap" of all the paths I found. The color of each point represents the last "target" point it was able to get to, with purple being the final point, outside of the maze.

The fractional part of the score was determined based on the sine of the sum of the angles and distances, which means that the input to sin() could be no more precise than to the tenths place. For the range of numbers that this sum could possibly be without adding a full point to my score, the tenth whose sine is closest to -1 is 11.0, and sin(11) is = -0.999990207.

Unfortunately, none of the few thousand paths that I had found added up to 11.0. However, I realized that I was only calling a_droite() in my path, and that if I replaced a_droite(x) with a_gauche(-x), x would be subtracted from the sum rather than added to it, without actually changing the validity of the path. I tried out every combination of a_droite and a_gauche calls for each of my few thousand paths, and found one that added up to 11.0, giving me a score of 71.0000097934493.

Here's the code that I used to find this path.

You'll notice that this is still very slightly off from my actual score - I realized that I could slightly decrease sin(sum) by slightly decreasing sum, and that I could slightly decrease sum by subtracting a tiny amount from each distance and angle. Normally, this would cause my score to increase by several full points because of the decimal places after the tenths place, but because the score is rounded to 5 decimal places before the length of the number is calculated, if the difference is less than 0.000005, you aren't penalized. So, I subtracted 0.0000049999... from each distance, to get a sum of 10.99991, a sine of -0.99999060081, and a final score of 71.00000939918644. I believe that this is within a floating-point error of the ideal solution.

Here's the solution that I submitted, for reference.

I actually tested all of this on a computer, as I didn't have my EP with me. I ported polycalc to use cv2 for drawing stuff.

I also tried to submit a few, uh, let's call them gimmicky, solutions. My first instinct was to try an integer overflow, but to my disappointment, Python doesn't actually have those. The numbers, they just keep going.

After that, I tried subclassing the float class so that it would return an empty string. Technically, this wasn't modifying the internal state of laby.py . I could have also returned a custom string class with a modified __len__ method, but in CPython __len__ must return a positive integer, which also gets converted into a regular integer, not one that I could subclass. Interestingly, MicroPython allows you to return a negative length for __len__, so I could have probably gotten a score of negative infinity if the admins didn't shut that idea down .

Finally, I also found a solution that's far better than the others that I decided not to submit since I was already in first. Here's the link if you want to give it a try for yourself.
(message original)



Conclusion

Ce sujet de labyrinthe était assez simple dans son ensemble, mais avec pas mal de subtilités qui ont bien fait ressortir ce qu'on espérait - des solutions de tous niveaux, avec des approches presques toutes différentes et pas mal de fun à la clé d'après vos témoignages.

Mon regret personnel sur cet énoncé c'est l'existence d'une solution unique. J'ai eu plusieurs retours expliquant que l'attrait d'un des défis les plus populaire du concours de rentrée (le défi de Python consistant à constituer une équipe de Pokémon efficace) est l'existence de multiples solutions même au voisinage des meilleurs scores. On a modifié à ce moment-là le deuxième sujet en introduisant un état, la vitesse du ballon. Chaque ordre se construit sur le précédent et donc on ne peut pas optimiser les ordres un à la fois, ce qui rend plus pénible l'exploration de tout l'espace de solutions.

Mais le sujet qui arrive vraiment à éviter ça est le défi du Léviathan puisque l'espace de solutions est formé de programmes et là les solutions seront vraiment toutes uniques. Ce défi est toujours en cours d'ailleurs, allez y jeter un oeil ou deux !

Un immense merci à tous les participants. J'espère que cet exercice vous aura plus, et on se retrouve bientôt pour les résultats du défi du Quetzalocoatl !

Commentez cette news ! (3)

Publié par Lephenixnoir le

Voir toutes les news


Concours de rentrée 2020 - Défi Python du Léviathan !


Salut à vous, visiteurs occasionnels et habitués de la communauté. Nous vous présentons aujourd'hui la troisième et ultime épreuve de notre événement de rentrée 2020 !


Si tu découvres cet événement maintenant, pas de problème ! Tu peux en lire les modalités dans l'annonce du défi Python de Xuanwu, le tout premier des défis du concours.

Ce concours de rentrée présente trois défis de programmation Python où tu dois optimiser un problème en écrivant un programme pour le résoudre. Les deux premiers étaient surtout mathématiques avec le programme utilisé pour fournir plus que calculer la solution, mais ce troisième est un pur exercice d'algorithmique.

• Le défi de Xuanwu était un exercice de tracé à la tortue (maintenant terminé).
• Le défi de Quetzalcoatl était un exercice de tracé par coordonnées (maintenant terminé).
• Le défi du Léviathan dont il est question dans cet article est un problème d'intelligence artificielle ouvert jusqu'au Dimanche 13 décembre 2020.

Eh oui, tu as bien entendu ! Ce défi fait s'affronter les IAs des participants dans la résolution d'un puzzle. Contrairement aux défis précédents, le programme ne doit pas résoudre une situation, mais doit exploiter les règles du jeu pour gagner le maximum de parties !

Alors voyons ensemble par quelle aventure on en est arrivés là !


Le défi Python du Léviathan

Après avoir découvert une caverne souterraine pleine de traces d'une civilisation ancienne, et traversé un labyrinthe géologique à l'aide d'une excavatrice abandonnée depuis fort longtemps durant le défi du Xuanwu, tu as expérimenté ton baptême de l'air en ballon lorsque l'engin multi-fonctions et toi avez été précipités dans les entrailles du sous-sol. Après avoir navigué avec succès les obstacles de ce défi de Quetzalcoatl, tu débouches enfin sur un volcan, et à court de gaz ta machine compagnon sombre dans la lave.


La longue colonne d'air et de roche autour du cratère comprend plusieurs dizaines de corniches et un certain nombre de tunnels... très certainement connectés par les anciens occupant du lieu. Mais tu n'as aucune idée de si tu peux sortir, et tu peux entendre quelque chose grogner en plus de chauves-souris.

Prise·e de panique, tu consultes la calculatrice que tu tiens toujours dans les mains, et constate que la fidèle excavatrice t'a laissé un ultime script pour t'aider à t'échapper. Le script mentionne qu'une des corniches mène à la surface mais est verrouillée par une clé cachée quelque part dans le volcan, et qu'un monstre appelé Léviathan vit dans les parages. Tu as trouvé un arc et une unique flèche dans l'excavatrice, donc peut-être que tu peux l'abattre... mais c'est un pari risqué.

Ton objectif est de trouver la clé et de sortir du volcan sans tomber dans un trou ni croiser le chemin du Léviathan. Le script possède quelques capteurs qui t'aideront à t'y retrouver :

• Le grognement du Léviathan permet de le détecter s'il est à moins de 2 corniches de toi (sur une voisine, ou une voisine d'une voisine).
• Les émanations d'air chaud permettent de détecter s'il y a un trou parmi les corniches voisines, mais pas où exactement.
• Le métal dans la clé peut aussi être détecte à une corniche de distance.
• Tu ne peux par contre voir la porte de sortir ou la présence de chauve-souris qu'une fois arrivé·e sur chaque corniche.

Les chauves-souris sont malicieuses. Initialement elles dorment, mais quand tu passes sur leur corniche elles se réveillent. Si tu reviens plus tard les déranger, elle sont sont susceptibles de t'attraper et de te déposer sur une corniche voisine pour que tu les laisses tranquilles.


Pour ce défi, il y a 3 scripts Python disponibles en bas de cet article.

polycal3.py est la bibliothèque de compatibilité graphique gérant les 13 environnements Python supportés par cette épreuve.
web.py implémente le volcan et les règles du jeu. À chaque partie le volcan est aléatoire !
webtest.py est une IA idiote qui décide tout au hasard, pour te servir de point de part dans ta quête.

Ton IA doit prendre la forme d'une fonction ia(corniche, voisines, taille, capteurs, evenements) que tu peux évaluer à l'aide la fonction parcourir_selon() :

from webtest import *
parcourir_selon(ia)

À chaque déplacement, la fonction ia() sera appelée pour te fournir les informations des capteurs :

taille indique le nombre de corniches (fixe)
corniche indique la corniche où tu te trouves actuellement (numérotée de 0 à taille-1)
voisines est la liste des corniches voisines (où tu peux te déplacer au prochain tour)
capteurs spécifie ce que le script sur ta calculatrice détecte.
capteurs & m_b indique la présence d'une chauve-souris sur la corniche actuelle
capteurs & (2 * m_b) indique qu'une chauve-souris est prête à se saisir de toi
capteurs & m_d indique la présence de la porte de sortie sur la corniche actuelle
capteurs & m_k indique la présence de la clé sur une des corniches voisines
capteurs & m_p alerte de la présence d'un ou plusieurs puits sur les corniches voisines
capteurs & m_l alerte de la présence du Léviathan sur une corniche voisine ou une voisine d'une voisine
evenements précise ce qui vient de se passer.
evenements & (2 * m_k) indique que tu as ramassé la clé de la sortie
evenements & (2 * m_a) indique que tu disposes d'une flèche et es donc capable de tirer
evenements & (2 * m_l) indique que la flèche que tu as tirée a touché mortellement le Léviathan

La fonction ia() doit retourner deux valeurs pour indiquer ta décision :

• D'abord le numéro d'une corniche voisine.
• Ensuite une action, 0 pour t'y déplacer, 1 pour y tirer ta flèche si tu penses que le Léviathan s'y trouve.

Dans le cas où une chauve-souris se saisit de toi, la réponse est ignorée : la chauve-souris te dépose où lui plaît.

Dans ce défi plus que jamais, tu as le droit d'utiliser tous les outils Python à ta disposition. Cependant, tu ne peux pas modifier web.py, ni accéder à ses variables internes, que ce soit en lecture ou en écriture. Ce serait t'attirer le malheur du Léviathan !

Les IAs seront évaluées sur leur performance dans un grand nombre d'instances fixes. Le but du jeu est de sortir sans dommages et le plus vite possible !


Comment participer

Pour participer, envoie ta participation par mail à l'addresse info@tiplanet.org avec :

• En objet, « Défi du Léviathan »
• Ton adresse postale complète avec ton nom et prénom
• Ton adresse mail (si différente de celle utilisée pour l'envoi)
• En option, ton pseudonyme sur TI-Planet ou Planète Casio (utilisé pour la liste des participants à la fin du concours)
• En option, par pure cosmétique, les badges à afficher dans notre classement à côté de tes participations : l'équipe Planète Casio ou TI-Planet, et la guilde Casio, HP, Lexibook, NumWorks, Symbolibre ou TI.
• Un numéro de téléphone personnel valide (utilisé uniquement en cas d'urgence, notamment en cas de problème avec une participation ou lors d'un choix de lot contraint par le temps)

Les communautés de TI-Planet et Planète Casio sont sensibles aux problématiques d'informations personnelles. Les informations que tu soumets seront utilisées uniquement pour le concours, puis supprimées lorsque l'événement sera terminé et les lots envoyés.


Lots de cette épreuve

Il y a 15 lots à remporter dans cette épreuve, fournis généreusement par les constructeurs Casio, Numworks, Texas Instruments, le revendeur Calcuso, Bernard Parisse de l'Institut Fourier (auteur de Xcas/KhiCAS), les associations CreativeCalc et UPECS gérant Planète Casio et TI-Planet, ainsi que Hewlett-Packard avec des goodies de 2019 !

Les participants ayant obtenus les 15 meilleurs scores au défi pourront choisir chacun à leur tour un lot de leur choix.

2 lots Capricorne ♑ comprenant 1 calculatrice Casio Graph 90+E, 1 pack de goodies Casio, 1 goodie Xcas, et 1 pack de goodies TI-Planet & Planète Casio

2 lots Bélier ♈ comprenant 1 solution d'émulation Casio, 1 CD de vidéos Casio fx-CG20 ou catalogue de produits Casio, 1 pack de goodies Casio, 1 goodie Xcas, et 1 pack de goodies TI-Planet & Planète Casio

Le CD contient 42 vidéos d'environ 8 heures par Jean-Michel Ferrard, originellement conçu pour la fx-CG 20 mais toujours applicable à la Graph 90+E, pour Windows et Mac.

La solution d'émulation Casio est au choix parmi :
• Une clé USB 8 Go d'émulation permanente, avec les émulateurs fx-92 Scientifique Collège+, Graph 35+E II 3.30, et Graph 90+E 3.40 à jour, pour Windows. Casio a annoncé que les mises à jour seront disponibles pour ces clefs dans le futur. Le modèle blanc est la clé Transcend 2019, le bleu est la clef EMTEC 2020.
• Une license de 3 ans permettant d'installer le fx-CP400 Manager (Windows/Mac) et le fx-CG 500 Manager (Windows/Mac). Les deux sont similaires à la ClassPad 400+E.





1 lot Serpentaire ⛎ comprenant 1 goodie HP, 1 goodie Xcas et 1 pack de goodies TI-Planète-Casio

La clé USB HP a une capacité de 16 Go, le poster mesure 59.2x40 cm.



3 lots Sagittaire ♐ comprenant 1 calculatrice NumWorks N0110, 1 pack de goodies NumWorks, 1 goodie Xcas, et 1 pack de goodies TI-Planet & Planète Casio

3 lots Balance ♎ comprenant 1 couvercle NumWorks, 1 autocollant NumWorks, 1 enveloppe ou carte postale ou carte de visite-énigme NumWorks, 1 pack de goodies NumWorks, 1 goodie Xcas et 1 pack de goodies TI-Planet & Planète Casio





1 lot Taureau ♉ comprenant 1 calculatrice TI-Nspire CX II-T CAS, 1 licence logiciel TI-Nspire CAS élève, 1 pack de goodies TI, 1 goodie Xcas, et 1 pack de goodies TI-Planète-Casio

1 lot Lion ♌ comprenant 1 calculatrice TI-Nspire CX II-T, 1 licence logiciel TI-Nspire élève, 1 pack de goodies TI, 1 goodie Xcas et 1 pack de goodies TI-Planète-Casio

1 lot Gémeaux ♊ comprenant 1 calculatrice TI-83 Premium CE Edition Python, 1 adaptateur USB, 1 clavier USB, 1 pack de goodies TI et 1 pack de goodies TI-Planète-Casio

1 lot Verseau ♒ comprenant 1 calculatrice TI-83 Premium CE Edition Python avec une gravure texte laser, 1 adaptateur USB, 1 clavier USB
dédié, 1 batterie de rechange, 1 chargeur mural, 1 housse Wyngs, 2 films de protection écran Wyngs dédiés, 1 extension de garantie 6 ans Calcuso, 1 pack de goodies TI et 1 pack de goodies TI-Planète-Casio

La gravure au laser de la TI-83 Premium CE Edition Python du lot Verseau est effectuée par Calcuso. Le gagnant choisissant ce lot devra nous communiquer le texte, dans la limite de 22 caractères et sans caractères spéciaux.





Tu peux trouver le détail des choix de goodies sur l'article TI-Planet annonçant le concours.



Ressources et téléchargement du programme

Scripts Python polycal3.py, web.py et webtest.py

Pour participer sur Graph 35+E II, il faut disposer de la mise à jour vers l'OS 3.30 qui introduit les fonctions de dessin en Python. Pour Graph 90+E, il faut de même avoir la mise à jour vers l'OS 3.40.

Mises à jour Python vers l'OS 3.30 et 3.40

Tu peux aussi utiliser un émulateur pour tester le script sur ton ordinateur ! Les émulateurs de Casio sont gratuits pendant 90 jours.

Émulateur Graph 35+E II version 3.30 pour Windows
Émulateur Graph 90+E version 3.40 pour Windows (lien direct)
Émulateur Graph 90+E version 3.40 pour Mac (lien direct)

Pour transférer les scripts Python, branche ta calculatrice avec un câble USB à l'ordinateur et appuie sur F1 (Flash USB). Ta Graph 35+E II et ta Graph 90+E se présente comme une clé USB à l'ordinateur. Tu peux alors coller les fichiers dans le dossier principal puis éjecter la pseudo-clé USB. Ensuite, lance les scripts depuis l'application Python !

Pour les autres modèles, vois dans l'article TI-Planet. Tu peux participer avec toutes les combinaisons calculatrice/Python suivantes !

• TI-83 Premium CE Edition Python / TI-84 Plus CE-T Python Edition
• Casio Graph 35+E II
• Casio Graph 90+E / fx-CG50
• HP Prime en mode CAS
• HP Prime avec appli Python intégrée (firmware instable, déconseillé)
• NumWorks (y compris Delta et Omega)
• NumWorks avec l'appli KhiCAS en mode Micropython (Delta uniquement)
• NumWorks avec l'appli KhiCAS en mode de compatibilité Python (Delta uniquement)
• TI-Nspire CX II
• TI-Nspire avec Ndless et Micropython
• TI-Nspire CX/CM avec Ndless et Micropython
• TI-Nspire CX avec Ndless et KhiCAS CX, en mode MicroPython ou en mode de compatibilité Python

Pour ce défi, la TI-83 Premium CE Python Edition et la TI-84 Plus CE-T Python Edition ne sont pas supportées. En effet, elles n'offrent que 16 ko de mémoire de travail, ce qui est bien insuffisant pour tout programme un minimum ambitieux.

C'est l'épreuve de programmation ultime que nous te présentons pour cet événement. Attrape ta calculatrice et conquiers le volcan par la stratégie et le croisement de l'information !

Les résultats des deux premiers défis suivront cette annonce. Stay tuned et à bientôt sur Planète Casio !

Article connexe sur TI-Planet : Concours de rentrée 2020 - défi Python du Léviathan

Commentez cette news ! (40)

Publié par Lephenixnoir le

Voir toutes les news


Lancement du vote du Jeu de la Rentrée 2020 !


Bonjour !
Suite au peu de votes du Lancement du vote du Jeu du Mois de Septembre, nous avons décidé d'élire LE jeu de la rentrée !


Rien de bien compliqué, vous votez, vous rentrez mon compte PayPal et vous me faites des dons pour que votre jeu soit sélectionné ! Et le programme avec le plus de voix gagne !

Je vous rappelle brièvement l'enjeux : Le gagnant est affiché 1 mois en page d'accueil et gagne le droit d'afficher ce trophée :



Et parfois ceux-là aussi
Cliquer pour enrouler


Mais c'est différent


Voici sans plus tarder les rêgles :


Règles


Ne pas voter plusieurs fois tu dois.
Un vote pour toi-même compté ne sera pas.
Aucun programme face à une note tu peux.

Exemple de classement : Nous avons les jeux Dumb Clicker 0, Dumb Clicker 1, Dumb Clicker 2, Dumb Clicker 3, Dumb Clicker 4. J'aime beaucoup Dumb Clicker 2, j'ai bien aimé jouer à Dumb Clicker 1, sans plus et je n'ai pas aimé les autres :
1-Dumb Clicker 2 (3pts)
2-
3-Dumb Clicker 1 (1pt)
Si j'ai bien aimé Dumb Clicker 0 mais pas les autres et que je pense que Sony aurait put être mieux ce vote serait approprié :
1-
2-Dumb Clicker 0 (2pts)
3-

Si j'ai adoré Dumb Clicker 1, Dumb Clicker 2 et Dumb Clicker 3, mais que je préfère Dumb Clicker 1 aux deux autres et que je trouve que la prestation de Dumb Clicker 2 est bâclée alors mon vote va ressembler à ça :
1-Dumb Clicker 1 (3pts)
2-Dumb Clicker 3 (2pts)
3-Dumb Clicker 2 (1pt)

Un Dumb Clicker baclé, vous vous rendez comptes ?


Les Jeux :

Les programmes sont triés par ordre alphabétique :

- Fxgnuboy de Djpadbit est un émulateur de Game Boy pour calculatrices monochromes SH4, pouvant faire tourner des jeux jusqu'à 90 fps avec overlock !

- Game Of Life de CaptainLuigi est un simulateur de vie contrairement à ce que son titre laisse entendre où vous devrez survivre dans le monde hostile qu'est l'époque moderne...

- Jeu de la vie de Oskar est une adaptation du célèbre jeu de la vie de John Conway, adapté en Basic Casio.

- Jeu de la vie python de Oskar est exactement le même programme mais développé en python, pour Graph 90+E ou Graph 35+E II.

- Snake extension de Polsulpicien est une extension de son jeu de Snake !

- Space_War de Palpatine_78 est un add-in pour 90+E où vous incarnez un X-Wing devant tuer un maximum de chasseurs TIE (aussi vilains que les membres de TI-Planet). Arriverez-vous à tous les tuer ?

- Bêtes (demo) de Pedrobzh est une ébauche d'un jeu, ne disposant seulement que d'un menu pour le moment

- ChessLink de Darkjura est un jeu d'échec... multijoueur ! Pas sûr que les profs de maths apprécient cette invention

Vous avez jusqu'à la semaine prochaine pour voter pour votre jeu préféré !

Et que le meilleur gagne !

À bientôt sur Planète Casio

Commentez cette news ! (1)

Publié par Tituya le

Voir toutes les news


Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2020 | Il y a 96 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd