Relation entre deux ensembles

Bonsoir
Je cherche un moyen un peu futé de mettre deux ensembles en relation. Je m'explique.

J'ai d'un côté une liste de codes (des entiers) qui correspondent à une condition météo. Et de l'autre, une liste de fichiers d'icônes. Les noms des icônes n'ont rien à voir avec ces codes. Je ne peux pas simplement changer les noms des icônes pour les appairer avec les codes pour deux raisons.

  • Un : plusieurs codes peuvent correspondre avec une même icône.
  • Deux : j'ai un second jeu de codes, venant d'un second site météo, et ces codes sont différents mais je devrai utiliser ces mêmes icônes.

Bref je cherche un moyen de mettre en relation mes ensembles de codes avec la liste des noms de fichiers d'icônes, sans passer par des tableaux ordonnés ou un switch / case ni une série de if...

Si quelqu'un a une idée originale...
Merci

Un b-tree ou plus simple un arbre binaire de recherche ?

En super pas du tout original, il y a le switch case...

Un premier switch à deux branches, une par site meteo.
Et dans chaque branche un second switch pour selectionner un fichier en fonction du code.

Pourquoi chercher midi à 14h?

Deux tableaux de structures, avec une fonction de recherche ?

struct icon
{
  int id;
  const char *filename;
};

struct icon iconList1[]
{
  1, "iconA",
  2, "iconB",
  13, "iconC",
  0
};

struct icon iconList2[]
{
  10, "iconA",
  12, "iconB",
  31, "iconC",
  0
};

char *getIconFile(struct icon *iconTable, int code)
{
  Serial.print("search icon for ");
  Serial.print(code);
  Serial.print(" ");
  for(int i = 0 ; iconTable[i].id != 0 ; i++) {
    if (iconTable[i].id == code) {
      Serial.println(iconTable[i].filename);
      return iconTable[i].filename;
    }
  }
  Serial.println("Not found");
  return NULL;
}

void setup()
{
  const char *filename;
  Serial.begin(115200);
  filename = getIconFile(iconList1, 13);
  filename = getIconFile(iconList1, 28);  // not found
  filename = getIconFile(iconList2, 12);
  filename = getIconFile(iconList2, 87);  // not found
}

void loop()
{
}

Normalement, si plusieurs chaînes constantes sont identiques, le compilateur ne les duplique pas, il utilise la même.

@+

Ou si vous voulez une recherche plus rapide au dépend de la place mémoire, organiser en arbre

--> C’est sortir l’artillerie lourde pour votre cas (les switch ou les tableaux de structure c'est suffisant), mais à titre de documentation:

Supposons que vous ayez 4 fichiers d'icônes

const char * icone0 = "icone0.jpg";
const char * icone1 = "icone1.jpg";
const char * icone2 = "icone2.jpg";
const char * icone3 = "icone3.jpg";

et en supposant que les codes que vous ayez soient 1 4 7 6 3 13 14 10 8, auquels sont associés une des images, on pourrait avoir l'approche suivante en prenant la structure d'arbre binaire de recherche :

Dans le code on définit une structure d'arbre à 2 branches qui comporte un code Météo, le pointeur vers le nom de fichier image associé à ce code et deux pointeurs vers branches de l'arbre.

struct arbre_binaire_t {
  const long codeMeteo;
  const char * icone;
  arbre_binaire_t * gauche;
  arbre_binaire_t * droite;
};

Puisque les associations valeurs / nom de l'image sont connues, on fabrique l'arbre à la main:

arbre_binaire_t code01 = { 1, icone2, NULL, NULL};
arbre_binaire_t code03 = { 3, icone0, NULL, NULL};
arbre_binaire_t code04 = { 4, icone3, NULL, NULL};
arbre_binaire_t code06 = { 6, icone1, NULL, NULL};
arbre_binaire_t code07 = { 7, icone2, NULL, NULL};
arbre_binaire_t code08 = { 8, icone0, NULL, NULL};
arbre_binaire_t code10 = {10, icone3, NULL, NULL};
arbre_binaire_t code13 = {13, icone1, NULL, NULL};
arbre_binaire_t code14 = {14, icone3, NULL, NULL};

Et comme on connait les valeurs (j'ai choisi ces nombres car ce sont ceux de l'image wikipedia)


On peut bâtir l'arbre en suivant les flèches

  racine = &code08;
  code08.gauche = &code03;
  code08.droite = &code10;
  code03.gauche = &code01;
  code03.droite = &code06;
  code06.gauche = &code04;
  code06.droite = &code07;
  code10.droite = &code14;
  code14.gauche = &code13;

En commençant la déclaration par les feuilles on peut tout bâtir à la compilation:

arbre_binaire_t code01 = { 1, icone2, NULL, NULL};
arbre_binaire_t code04 = { 4, icone3, NULL, NULL};
arbre_binaire_t code07 = { 7, icone2, NULL, NULL};
arbre_binaire_t code13 = {13, icone1, NULL, NULL};
arbre_binaire_t code06 = { 6, icone1, &code04, &code07};
arbre_binaire_t code03 = { 3, icone0, &code01, &code06};
arbre_binaire_t code14 = {14, icone3, &code13, NULL};
arbre_binaire_t code10 = {10, icone3, NULL, &code14};
arbre_binaire_t code08 = { 8, icone0, &code03, &code10};
arbre_binaire_t * racine = &code08;

Voilà ensuite il ne reste plus qu'à écrire une petite fonction récursive trouveCode() de parcours d'arbre qui va trouver, pour un code météo donné, le nom du fichier image.

Je suis sur mon smartPhone et j'ai pas accès au compilateur, mais ça donnerait un truc comme cela - aux fautes de frappes potentielles près:

struct arbre_binaire_t {
  const long codeMeteo;
  const char * icone;
  arbre_binaire_t * gauche;
  arbre_binaire_t * droite;
};

const char * icone0 = "icone0.jpg";
const char * icone1 = "icone1.jpg";
const char * icone2 = "icone2.jpg";
const char * icone3 = "icone3.jpg";

// on construit l'arbre binaire à la main puisqu'on connait les valeurs
arbre_binaire_t code01 = { 1, icone2, NULL, NULL};
arbre_binaire_t code04 = { 4, icone3, NULL, NULL};
arbre_binaire_t code07 = { 7, icone2, NULL, NULL};
arbre_binaire_t code13 = {13, icone1, NULL, NULL};
arbre_binaire_t code06 = { 6, icone1, &code04, &code07};
arbre_binaire_t code03 = { 3, icone0, &code01, &code06};
arbre_binaire_t code14 = {14, icone3, &code13, NULL};
arbre_binaire_t code10 = {10, icone3, NULL, &code14};
arbre_binaire_t code08 = { 8, icone0, &code03, &code10};
arbre_binaire_t * racine = &code08;

const char * trouveCode(const byte code, arbre_binaire_t* arbre)
{
  if (arbre == NULL) return NULL;
  if (arbre->codeMeteo == code) return arbre->icone;
  if (code > arbre->codeMeteo) return trouveCode(code, arbre->droite);
  return trouveCode(code, arbre->gauche);
}

void printCodes(arbre_binaire_t* arbre)
{
  if (arbre == NULL) return;
  printCodes(arbre->gauche);
  printCodes(arbre->droite);
  Serial.print(arbre->codeMeteo); Serial.print(" ");
}


void setup()
{
  Serial.begin(115200);
  Serial.setTimeout(10);
}

void loop() {
  Serial.println(F("-----------"));
  Serial.print(F("Codes valides: "));
  printCodes(racine);
  Serial.print(F("\nEntrez un code:"));
  while (Serial.available() == 0);
  long code = Serial.parseInt();
  Serial.println(code);
  const char * nomDufichier = trouveCode(code, racine);
  if (nomDufichier == NULL) {
    Serial.println(F("ERREUR - CODE INCONNU"));
  } else {
    Serial.print(F("L'image pour le code "));
    Serial.print(code);
    Serial.print(F(" est "));
    Serial.println(nomDufichier);
  }
}

En mettant la console série à 115200 bauds et qui ne renvoie rien en fin de ligne vous devriez avoir moyen de saisir un code, suivi de "entrée", et voir le nom de fichier associé si je ne le suis pas trompé

Have fun!

hbachetti:
Normalement, si plusieurs chaînes constantes sont identiques, le compilateur ne les duplique pas, il utilise la même.

Un moyen de vérifier:

struct icon
{
  int id;
  const char *filename;
};

struct icon iconList1[]
{
  1, "iconA",
  2, "iconB",
  13, "iconC",
  0
};

struct icon iconList2[]
{
  10, "iconA",
  12, "iconB",
  31, "iconC",
  0
};

void setup() {
  Serial.begin(115200);
  for (int i = 0; i < 3; i++) {
    Serial.print(i);
    if (iconList1[i].filename  == iconList2[i].filename) Serial.println(F("\tLe compilateur a bien fait sont travail"));
    else Serial.println(F("\tLe compilateur doit revoir sa copie... (ou le programmeur)"));
  }
}

void loop() {}

(j'ai pas pu tester mais je crois que vous avez raison, le préprocesseur généralement identifie bien ces cas)

0	Le compilateur a bien fait sont travail
1	Le compilateur a bien fait sont travail
2	Le compilateur a bien fait sont travail

Tout va bien. :smiley:

@+

:slight_smile: :slight_smile:

si vous avez un compilateur sous la main, il tourne mon programme avec l'arbre?

Oui, pas de problème.

-----------
Codes valides: 1 4 7 6 3 13 14 10 8 
Entrez un code:4
L'image pour le code 4 est icone3.jpg
-----------
Codes valides: 1 4 7 6 3 13 14 10 8 
Entrez un code:4
L'image pour le code 4 est icone3.jpg
-----------
Codes valides: 1 4 7 6 3 13 14 10 8 
Entrez un code:2
ERREUR - CODE INCONNU
-----------
Codes valides: 1 4 7 6 3 13 14 10 8 
Entrez un code:

Cool :slight_smile:

Merci à tous
Je pense que je vais faire simple, et utiliser la struct. J'étudierai le reste plus tard.
Joyeuses fêtes de fin d'année !