Partage
  • Partager sur Facebook
  • Partager sur Twitter

zRom

Venez vous amuser avec les chiffres romains

    18 juin 2011 à 14:23:10

    Période: été 2011
    Sujet: Boucles, manipulation de chaînes de caractères

    zRom



    L'exercice de ce mois nous fera voyager dans un autre pays assez connu qui est : l'Italie !
    Non, non, je ne vous offre pas un voyage tous frais payés, nous allons utiliser les chiffres romains !

    Les chiffres romains



    Vous connaissez sûrement les chiffres romains, ils sont utilisés un peu partout, pour les siècles (XXè siècle), le nom de rois (Louis XVI, Henri IV), les montres, les chapitres de documents, les numéros de page, etc. .
    Mais la question est : savez-vous compter en nombre romain et savez-vous comment ça fonctionne ?
    L'exercice du moment nous aidera justement à faire la conversion chiffres arabes (notre système de compter 0,1,2,etc.) et les chiffres romains (ainsi que l'inverse).
    Quelques explications s'imposent. :)

    Tout d'abord, on va présenter les nombres (qui sont en fait des lettres) et nombres arabes :

    Arabes Romains
    0 Inexistant
    1 I
    5 V
    10 X
    50 L
    100 C
    500 D
    1000 M

    Pour compter, c'est très simple, il suffit de lire le nombre de droite à gauche (vous pouvez aussi le faire de gauche à droite, seulement c'est plus simple de droite à gauche ;) ) et d'additionner tous les nombres. A une exception près, si le nombre qui précède le nombre 'courant' est inférieur à celui-ci, on le soustrait. Fastoche, non ? :)
    On va se fixer une règle : on ne peut soustraire qu'un nombre au nombre juste en dessous. Donc, on ne soustrait I qu'à V ou X, X qu'à L ou C, C qu'à D ou M (j'ai zappé ceux qui étaient inutiles).
    Les soustractions sont assez rare si vous remarquez bien, on notera le 4 et le 9, le reste... pas grand chose à voir. :D
    Leur système de comptage ne permet d'écrire que des nombres jusqu'à 4999. Dans nos exercices, on se limitera à 3999.

    Un peu de comptage :

    2 s'écrit II
    3 s'écrit III
    4 peut s'écrire IIII ou IV (I précède V, donc on soustrait 1 à 5 -> 4)
    29 peut s'écrire XXVIIII (10+10+5+1+1+1+1) ou XXIX (10+10+(10-1))
    90 s'écrit XC (100-10)

    Je pense que vous aurez compris, rien de bien compliqué !

    Exercice 1


    Vous devez écrire un programme qui prend un nombre romain dans sa forme correcte et la plus courte (l'utilisateur est intelligent) et donne le résultat en nombre arabe.

    Exercice 2


    Vous devez écrire un programme qui prend un nombre arabe et le convertit en nombre romain dans sa forme la plus courte.

    Exercice 3


    Vous devez écrire un programme qui prend un nombre romain quelconque et écrit sa forme arabe ainsi que sa forme romaine la plus courte.

    Bon courage. :)
    • Partager sur Facebook
    • Partager sur Twitter
      18 juin 2011 à 14:50:59

      très bonne initiative. Ça a l'aire marrent.
      • Partager sur Facebook
      • Partager sur Twitter
        18 juin 2011 à 14:56:42

        Intéressant, j'essayerai peut-être de le faire ! ;)

        Citation : Pouet_forever


        29 peut s'écrire XXVIII (10+10+V+1+1+1+1) ou XXIX (10+10+(10-1))



        Une petite faute :p : tu as oublié un I (29 peut s'écrire XXVIIII) et tu as écrit (10+10+V+1+1+1+1) au lieu de (10+10+5+1+1+1+1)
        Par contre, es-tu certain que 4 puisse s'écrire IIII ?
        • Partager sur Facebook
        • Partager sur Twitter
          18 juin 2011 à 15:09:37

          4 peut s'écrire IIII pour l'exercice 3 :
          je rentre IIII et le programme me répond
          4, IV
          • Partager sur Facebook
          • Partager sur Twitter
            18 juin 2011 à 15:14:53

            @robinson des bois: Exactement , par exemple.

            @ Loquerems: Si on suit les règles définis plus haut(en dessous du tableau), 4 peux effectivement s'écrire IIII ou IV.
            • Partager sur Facebook
            • Partager sur Twitter

            🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.

              18 juin 2011 à 15:47:37

              Bonjour M'sieur Pouet !

              L'exercice 2 avait l'air rigolo, du coup j'ai bricolé ce qui suit en pas très longtemps. Ca à l'air de fonctionner à peu près.

              #include <stdlib.h>
              #include <stdio.h>
              #include <string.h>
              
              #define	STR_LG	32
              
              int Arab2Roman(int nNb, char *pDst)
              {
              	static char *gpRoman[] =
              	{
              		"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX",
              		"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC",
              		"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM",
              		"", "M", "MM", "MMM", "MMMM", "", "", "", "", ""
              	};
              
              	char	pConv[STR_LG];
              	char	*pPtr = pConv;
              	int		nCur;
              
              	*pDst = 0;
              	if (nNb < 0)
              	{
              		*pDst = '-';
              		*(pDst + 1) = 0;
              		nNb = -nNb;
              	}
              	if (nNb > 4999)
              	{
              		printf("Les nombres romains ne vont que jusqu'a 4999.\n");
              		return (1);
              	}
              
              	itoa(nNb, pConv, 10);
              	nCur = strlen(pConv);
              	while (nCur)
              	{
              		nCur--;
              		strcat(pDst, gpRoman[(nCur * 10) + ((*pPtr++) - '0')]);
              	}
              	return (0);
              }
              
              int main(void)
              {
              	char	pDst[STR_LG];
              	int		nNb;
              
              	printf("Entrez un nombre a convertir en chiffres romains (1-4999) : ");
              	scanf("%d", &nNb);
              
              	if (Arab2Roman(nNb, pDst) == 0)
              		printf("Representation de %d en chiffres romains : %s\n", nNb, pDst);
              
              	return (0);
              }
              


              (Oui bon, j'ai utilisé des tableaux statiques pour les chaines et c'est pas trop commenté, mais bon, c'était pour voir ! :) ).

              Clément.
              • Partager sur Facebook
              • Partager sur Twitter
                18 juin 2011 à 16:41:52

                Je ne crois pas que 4 puisse s'écrire IIII. La règle est qu'acun symbole ne doit se répéter plus de 3 fois de suite. Au trmps pour moi j'ai tord.

                Mais sinon c'est sympa comme idée :)
                • Partager sur Facebook
                • Partager sur Twitter
                  18 juin 2011 à 16:45:54

                  Voir ici.

                  Partie: Nos chiffres traduits en notation romaine

                  @ joe78: itoa :(
                  • Partager sur Facebook
                  • Partager sur Twitter

                  🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.

                    18 juin 2011 à 17:39:00

                    En fait, c'est du vieux romain. Dans le vieux romain, on pouvait écrire 4 IIII mais il y a eu une révision du langage et donc on s'est mis à écrire 4 IV.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      18 juin 2011 à 18:07:37


                      Pour faire suite à la fonction Arab2Roman() de joe78
                      Voici un exemple de fonction qui fait l'inverse
                      (Conversion d'un nombre Romain en nombre Arabe)


                      int Roman2Arab(char *roman, int *arab)
                      {
                        int i;
                        char buf[32];
                      
                        for(i = 1; i <= 4999; i++)
                        {
                          if(!Arab2Roman(i, buf)) //La fonction de joe78
                          {
                            if(!stricmp(buf, roman))
                            {
                              *arab = i;
                              return 1;
                            }
                          }
                        }
                      
                        return 0;
                      }
                      



                      ou



                      int Roman2Arab(char *roman)
                      {
                        int i;
                        char rom[32];
                      
                        for(i = 1; i <= 4999; i++)
                        {
                          if(!Arab2Roman(i, rom)) //La fonction de joe78
                          {
                            if(!stricmp(rom, roman))
                              return i;
                          }
                        }
                      
                        return 0;
                      }
                      


                      • Partager sur Facebook
                      • Partager sur Twitter
                        18 juin 2011 à 18:20:34

                        magma, un peu long lourd ton truck tu crois pas ?

                        • Partager sur Facebook
                        • Partager sur Twitter

                        🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.

                          18 juin 2011 à 18:31:00

                          Salut.

                          L'exercice est sympa, voilà pour le 3e :
                          #include <stdio.h>
                          #include <string.h>
                          
                          int romainVersArabe(char *str)
                          {
                              int vals[256]  = {0};
                              int i, res=0;
                          
                              vals['I'] = 1; 
                              vals['V'] = 5;
                              vals['X'] = 10;
                              vals['L'] = 50;
                              vals['C'] = 100;
                              vals['D'] = 500;
                              vals['M'] = 1000;
                          
                              for(i=0; str[i]; i++)
                              {
                                  if(vals[(int)str[i+1]] > vals[(int)str[i]])
                                      res -= vals[(int)str[i]];
                                  else
                                      res += vals[(int)str[i]];
                              }
                          
                              return res;
                          }
                          
                          char *arabeVersRomain(int N, char *str)
                          {
                              const char *p10[] = {"I", "X", "C", "M"}, *p5[] = {"V","L","D"};
                              int size, i;
                          
                              str[0] = 0;
                              for(i=0; N > 0; i++)
                              {
                                  if(N%5 == 4)
                                  {
                                      if(N%10 == 4)
                                          strcat(str, p5[i]);
                                      if(N%10 == 9)
                                          strcat(str, p10[i+1]);
                                      strcat(str, p10[i]);
                                  }
                                  else
                                  {
                                      int j=0;
                                      for(j=0; j<N%5; j++)
                                          strcat(str, p10[i]);
                                      if(N%10 >= 5)
                                          strcat(str, p5[i]);
                                  }
                                  N /= 10;
                              }
                          
                              size = strlen(str);  /*On retourne la chaine*/
                              for(i=0; i<size/2; i++)
                              {
                                  int temp = str[i];
                                  str[i] = str[size-i-1];
                                  str[size-i-1] = temp;
                              }
                          
                              return str;
                          }
                          
                          int main(void)
                          {
                              char romain[100] = ""; 
                              int resultat;
                          
                              printf("Entrez un nombre en chiffre romains :\n");
                              scanf("%s", romain);
                              resultat = romainVersArabe(romain);
                              printf("Valeur en chiffres arabes : %d\n", resultat);
                              printf("Ecriture correcte en chiffres romains : %s\n", arabeVersRomain(resultat, romain));
                          
                              return (0);
                          }
                          


                          Citation

                          L'exercice 2 avait l'air rigolo, du coup j'ai bricolé ce qui suit en pas très longtemps. Ca à l'air de fonctionner à peu près.

                          Wow chapeau, l'implémentation de ton algo est vraiment astucieuse je trouve, en tout cas je n'en avais jamais vu une aussi simple...
                          • Partager sur Facebook
                          • Partager sur Twitter
                            18 juin 2011 à 19:07:48

                            @ Twisted Destiny:
                            Mhh :
                            • Tu pourrais faire une vérifications pour les nombres supérieures à 3999 ? Pour pas afficher les symbole bazars.
                            • Un peu lourd 256 cases pour seulement 7 cases utiles, non ?
                            • Tu pourrais géré les nombres entrer en minuscules ?

                            • Partager sur Facebook
                            • Partager sur Twitter

                            🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.

                            Anonyme
                              18 juin 2011 à 19:40:03

                              Salut!
                              J ai tente un truc dans ce style mais j arrive pas a le faire fonctionner !
                              Seriez vous pourquoi???

                              int romainArabe(char *chiffre)
                              {
                                  char nbRomain[] = {"IVXLCDM"};
                                  int valeuNbRomain[] = {1,5,10,50,100,500,1000},i,j,res=0;
                              
                                  for(i=strlen(chiffre);i>=0;i--)
                                  {
                                      for(j=0;j<strlen(nbRomain);j++)
                                      {
                                          if(chiffre[i] == nbRomain[j])
                                          {
                                              if(chiffre[i+1] > chiffre[i])
                                              {
                                                  res -= valeuNbRomain[i];
                                              }
                                              else
                                              {
                                                  res += valeuNbRomain[i];
                                              }
                                          }
                                      }
                              
                                  }
                                  return res;
                              }
                              
                              • Partager sur Facebook
                              • Partager sur Twitter
                                18 juin 2011 à 19:50:17

                                @ben83510 :
                                Ce n'est pas vraiment l'endroit pour poster une question, créer plutôt un autre topic. Par-contre, tu confonds 'i' et 'j' à partir de if(chiffre[i] == nbRomain[j]) tu dois utiliser 'j'.
                                • Partager sur Facebook
                                • Partager sur Twitter

                                🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.

                                  18 juin 2011 à 20:19:18

                                  Bonjour,

                                  Citation

                                  * Tu pourrais faire une vérifications pour les nombres supérieures à 3999 ? Pour pas afficher les symbole bazars.
                                  * Un peu lourd 256 cases pour seulement 7 cases utiles, non ?
                                  * Tu pourrais géré les nombres entrer en minuscules ?


                                  Merci pour tes remarques.

                                  *Oui, pourquoi pas, au cas ou il entrerait un nombre entre 4000 et 4999...
                                  *256 ce n'est pas lourd du tout, c'est même très petit. Par contre si tu trouve un moyen aussi simple pour gérer ce tableau, qui n'utilise que 7 cases, moi je dis pas non (mais ça m'étonnerait)
                                  *Oui ça ne couterait rien en effet

                                  Avec tes 2 améliorations :
                                  #include <stdio.h>
                                  #include <string.h>
                                  
                                  int romainVersArabe(char *str)
                                  {
                                      int vals[256]  = {0};
                                      int i, res=0;
                                  
                                      vals['I'] = vals['i'] = 1; 
                                      vals['V'] = vals['v'] = 5;
                                      vals['X'] = vals['x'] = 10;
                                      vals['L'] = vals['l'] = 50;
                                      vals['C'] = vals['c'] = 100;
                                      vals['D'] = vals['d'] = 500; 
                                      vals['M'] = vals['m'] = 1000;
                                  
                                      for(i=0; str[i]; i++)
                                      {
                                          if(vals[(int)str[i+1]] > vals[(int)str[i]])
                                              res -= vals[(int)str[i]];
                                          else
                                              res += vals[(int)str[i]];
                                      }
                                  
                                      return res;
                                  }
                                  
                                  char *arabeVersRomain(int N, char *str)
                                  {
                                      const char *p10[] = {"I", "X", "C", "M"}, *p5[] = {"V","L","D"};
                                      int size, i;
                                  
                                      str[0] = 0;
                                      for(i=0; N > 0; i++)
                                      {
                                          if(N%5 == 4)
                                          {
                                              if(N%10 == 4)
                                                  strcat(str, p5[i]);
                                              if(N%10 == 9)
                                                  strcat(str, p10[i+1]);
                                              strcat(str, p10[i]);
                                          }
                                          else
                                          {
                                              int j=0;
                                              for(j=0; j<N%5; j++)
                                                  strcat(str, p10[i]);
                                              if(N%10 >= 5)
                                                  strcat(str, p5[i]);
                                          }
                                          N /= 10;
                                      }
                                  
                                      size = strlen(str);  /*On retourne la chaine*/
                                      for(i=0; i<size/2; i++)
                                      {
                                          int temp = str[i];
                                          str[i] = str[size-i-1];
                                          str[size-i-1] = temp;
                                      }
                                  
                                      return str;
                                  }
                                  
                                  int main(void)
                                  {
                                      char romain[100] = ""; 
                                      int resultat;
                                  
                                      printf("Entrez un nombre en chiffre romains (compris entre 1 et 3999) :\n");
                                      scanf("%s", romain);
                                      resultat = romainVersArabe(romain);
                                      if(resultat > 3999)
                                          printf("Vous avez ecris n'importe quoi\n");
                                      printf("Valeur en chiffres arabes : %d\n", resultat);
                                      printf("Ecriture correcte en chiffres romains : %s\n", arabeVersRomain(resultat, romain));
                                      
                                      return (0);
                                  }
                                  

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    18 juin 2011 à 20:27:24

                                    2 tableaux dont l'indice permettrait de faire correspondre les valeurs. Par exemple.
                                    • Partager sur Facebook
                                    • Partager sur Twitter

                                    🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.

                                      18 juin 2011 à 20:39:08

                                      Citation : @che

                                      2 tableaux dont l'indice permettrait de faire correspondre les valeurs. Par exemple.

                                      Je ne vois pas ou tu veux en venir. Peux-tu montrer un exemple?

                                      Par contre j'ai une question (problème que j'ai rencontré en codant mon code), pourquoi le compilateur n'est pas content lorsque j'utilise un char pour l'indice de mon tableau. Par exemple, ici (j'ai dû faire un cast) :

                                      res -= vals[(int)str[i]];
                                      
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        18 juin 2011 à 21:00:28

                                        Salut,

                                        Intéressant ce petit exercice :)

                                        Citation : Twisted Destiny


                                        Par contre j'ai une question (problème que j'ai rencontré en codant mon code), pourquoi le compilateur n'est pas content lorsque j'utilise un char pour l'indice de mon tableau. Par exemple, ici (j'ai dû faire un cast) :



                                        Parce que le type char peut être signé ou non signé suivant la machine. Cela peut réserver des surprises ;)
                                        Sinon, voici mon code pour le premier exercice (conversion Romains -> Arabes):


                                        #include <stdio.h>
                                        #include <stdlib.h>
                                        #include <string.h>
                                        
                                        
                                        static char const *Nombres[] = { "IV", "IX", "XL", "XC", "CD", "CM", "I", "V",
                                                                         "X" , "L" , "C" , "D" , "M" };
                                        
                                        static long const Valeurs[]  = {  4  ,  9  ,  40 ,  90 , 400 , 900 ,  1 ,  5 ,
                                                                         10  , 50  , 100 , 500 , 1000 };
                                        
                                        long
                                        rtoa (char const *s)
                                        {
                                           long n = 0;
                                        
                                           while (*s) {
                                              unsigned i;
                                        
                                              for (i = 0; i < sizeof Nombres; i++) {
                                                 if (strncmp (s, Nombres[i], strlen (Nombres[i])) == 0) {
                                                    n += Valeurs[i];
                                                    s += strlen (Nombres[i]);
                                                    break;
                                                 }
                                              }
                                           }
                                        
                                           return n;
                                        }
                                        
                                        
                                        int
                                        main (void)
                                        {
                                           char buffer[32];
                                        
                                           if (scanf ("%31s", buffer)) {
                                              long n;
                                        
                                              n = rtoa (buffer);
                                              printf ("%ld\n", n);
                                           }
                                        
                                           return EXIT_SUCCESS;
                                        }
                                        

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          18 juin 2011 à 21:10:57

                                          Citation : Pouet_forever


                                          Je pense que vous aurez compris, rien de bien compliqué !



                                          Hum, je trouve pas que ce soit si facile ...

                                          Citation : Pouet_forever

                                          un nombre romain dans sa forme correcte et la plus courte (l'utilisateur est intelligent) et donne le résultat en nombre arabe.


                                          nombre romain ... nombre arabe, ça fait bizarre comme formulation, je pense que tu pourrais dire nombre en chiffres arabes, nombre en chiffres romains.




                                          Citation : Pouet_forever


                                          zRom



                                          zRom ? titre curieux, j'ai pensé à une ROM (read only memory) embarquée, je dois être un peu obsédé ;) Je sais pas sinon: zÉsar, zRome, zRomains, etc.


                                          Citation : Pouet_forever



                                          Exercice 1


                                          Vous devez écrire un programme qui prend un nombre romain dans sa forme correcte et la plus courte (l'utilisateur est intelligent) et donne le résultat en nombre arabe.

                                          Exercice 2


                                          Vous devez écrire un programme qui prend un nombre arabe et le convertit en nombre romain dans sa forme la plus courte.

                                          Exercice 3


                                          Vous devez écrire un programme qui prend un nombre romain quelconque et écrit sa forme arabe ainsi que sa forme romaine la plus courte.



                                          Plus court, plus long je vois pas trop l'intérêt, pour moi il n'y a qu'un forme d'écriture.


                                          J'avais écrit des codes il y a deux ou trois ans, je les ressors pour ainsi dire tels quels :

                                          #include <stdio.h>
                                          #include <string.h>
                                          
                                          void decimal_vers_romain(char *romain, int x)
                                          {
                                          #define  MILLIERS 4
                                            char *dix = "IXCM";
                                            char *cinq = "VLD";
                                            int position_decimal = 0, position_romain = 0;
                                            int i, nb_chiffres;
                                            char decimal[5];
                                          
                                            nb_chiffres = sprintf(decimal, "%d", x);
                                            for (i = 0; i < nb_chiffres; i++)
                                              decimal[i] -= '0';
                                          
                                            for (; position_decimal < nb_chiffres; position_decimal++)
                                              {
                                                char chiffre = decimal[position_decimal];
                                                int type_chiffre = nb_chiffres - position_decimal - 1;
                                          
                                                if (type_chiffre == MILLIERS)
                                                  for (i = 0; i < chiffre; i++)
                                                    romain[position_romain++] = 'M';
                                                else
                                                  switch (chiffre)
                                                    {
                                                    case 1:
                                                    case 2:
                                                    case 3:
                                                      for (i = 0; i < chiffre; i++)
                                                        romain[position_romain++] = dix[type_chiffre];
                                                      break;
                                                    case 4:
                                                      romain[position_romain++] = dix[type_chiffre];
                                                      romain[position_romain++] = cinq[type_chiffre];
                                                      break;
                                                    case 5:
                                                      romain[position_romain++] = cinq[type_chiffre];
                                                      break;
                                                    case 6:
                                                    case 7:
                                                    case 8:
                                                      romain[position_romain++] = cinq[type_chiffre];
                                                      for (i = 0; i < chiffre - 5; i++)
                                                        romain[position_romain++] = dix[type_chiffre];
                                                      break;
                                                    case 9:
                                                      romain[position_romain++] = dix[type_chiffre];
                                                      romain[position_romain++] = dix[type_chiffre + 1];
                                                      break;
                                                    }
                                              }
                                          }
                                          
                                          int romain_vers_decimal(char *romain)
                                          {
                                            char chiffresRomains[] = "IVXLCDM";
                                            int valeursDecimales[sizeof(chiffresRomains) - 1] =
                                              { 1, 5, 10, 50, 100, 500, 1000 };
                                            int nb_chiffres = strlen(romain), i, ancien, nouveau;
                                            int resultat;
                                          
                                            ancien = strchr(chiffresRomains, romain[nb_chiffres - 1]) - chiffresRomains;
                                            resultat = valeursDecimales[ancien];
                                          
                                            for (i = nb_chiffres - 2; i >= 0; i--)
                                              {
                                                nouveau = strchr(chiffresRomains, romain[i]) - chiffresRomains;
                                                if (nouveau >= ancien)
                                                  resultat += valeursDecimales[nouveau];
                                                else
                                                  resultat -= valeursDecimales[nouveau];
                                                ancien = nouveau;
                                              }
                                            return resultat;
                                          }
                                          
                                          
                                          
                                          int main(void)
                                          {
                                            int i;
                                            char romain[100] = { 0 };
                                          
                                            /* exemple inspirés par
                                               http://en.wikipedia.org/wiki/Roman_numerals#Modern_Roman_numerals */
                                            char *romains[] =
                                              { "DCLXVI", "MDCLXVI", "MCCCCCCVI", "MMMDCCCLXXXVIII", "MMMCMXCIX" };
                                          
                                            for (i = 0; i < (int) (sizeof romains / sizeof *romains); i++)
                                              printf("%s = %d\n", romains[i], romain_vers_decimal(romains[i]));
                                            decimal_vers_romain(romain, 2011);
                                            printf("%s = %d\n", romain, 2011);
                                          
                                            /* Test complet de 1 à 3999 */
                                            for (i = 1; i < 4000; i++)
                                              {
                                                char romain[100] = { 0 };
                                                decimal_vers_romain(romain, i);
                                                if (romain_vers_decimal(romain) != i)
                                                  {
                                                    printf("%d %s : calcul faux\n", i, romain);
                                                    return 0;
                                                  }
                                              }
                                            printf("Test 1 -> 3999 : OK\n");
                                          
                                            return 0;
                                          }
                                          


                                          DCLXVI = 666
                                          MDCLXVI = 1666
                                          MCCCCCCVI = 1606
                                          MMMDCCCLXXXVIII = 3888
                                          MMMCMXCIX = 3999
                                          MMXI = 2011
                                          Test 1 -> 3999 : OK


                                          Les exemples proviennent de wikipedia qui contient également un code de conversion arable -> romain (c'est le cas le plus facile des deux).


                                          Le fil de discussion ICI pourra être utile.
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            18 juin 2011 à 23:06:42

                                            Citation : Twisted Destiny

                                            Citation : @che

                                            2 tableaux dont l'indice permettrait de faire correspondre les valeurs. Par exemple.

                                            Je ne vois pas ou tu veux en venir. Peux-tu montrer un exemple? :D


                                            Exemple :
                                            int value[]  = {1000, 500, 100, 50, 10, 5, 1}; /* Les nombres correspondants aux chiffre romain */
                                            char *digit = "MDCLXVI";                       /* Les chiffres romains par ordre décroissant */
                                            

                                            La position permet de passer de l'un a l'autre.
                                            • Partager sur Facebook
                                            • Partager sur Twitter

                                            🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.

                                              18 juin 2011 à 23:39:16

                                              Citation : joe78


                                              itoa(nNb, pConv, 10);
                                              




                                              C'est portable ?


                                              Citation : Taurre


                                              Parce que le type char peut être signé ou non signé suivant la machine. Cela peut réserver des surprises ;)



                                              Oui mais je vois pas en quoi c'est un problème (tu peux très bien avoir des indices négatifs dans un tableau). En tous cas chez moi, aucun avertissement.

                                              Citation : @che


                                              int value[]  = {1000, 500, 100, 50, 10, 5, 1}; /* Les nombres correspondants aux chiffre romain */
                                              char *digit = "MDCLXVI";                       /* Les chiffres romains par ordre décroissant */
                                              


                                              La position permet de passer de l'un a l'autre.



                                              Oui mais c'est quand même très lourd un truc comme ça, un des défauts du C de ne pas avoir nativement des tableaux associatifs, je suppose qu'en C++ on n'a pas ce genre de lacune.
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                18 juin 2011 à 23:43:59

                                                Sympa comme truc :p


                                                #ifndef ZROM_H
                                                #define ZROM_H
                                                
                                                /* constants ================================================================ */
                                                #define ZROM_LONGEST "MMMDCCCLXXXVIII"
                                                
                                                /* types ==================================================================== */
                                                typedef struct zrom_t zrom_t; 
                                                
                                                /* public functions ========================================================= */
                                                zrom_t * zrom_create(void);
                                                void zrom_delete(zrom_t * zrom);
                                                
                                                const char * zrom_get_string(const zrom_t * zrom);
                                                int zrom_get_value(const zrom_t * zrom);
                                                
                                                /* ex. 1 */
                                                int zrom_set_string(zrom_t * zrom, const char * string);
                                                
                                                /* ex. 2 */
                                                int zrom_set_value(zrom_t * zrom, int value);
                                                
                                                /* ex. 3 */
                                                void zrom_sanitize_string(zrom_t * zrom);
                                                
                                                #endif
                                                

                                                #include "zrom.h"
                                                
                                                #include <stdlib.h>
                                                #include <string.h>
                                                #include <errno.h>
                                                
                                                /* structures =============================================================== */
                                                struct zrom_t {
                                                    char string[sizeof ZROM_LONGEST];
                                                    int value;
                                                };
                                                
                                                /* private functions ======================================================== */
                                                static int zrom_validate_string(const char * string) {
                                                    int valid;
                                                
                                                    if (strlen(string) < sizeof ZROM_LONGEST) {
                                                        int i = 0;
                                                        
                                                        valid = 1;
                                                        
                                                        while (string[i] && valid) {
                                                            switch (string[i]) {
                                                                case 'M':
                                                                case 'D':
                                                                case 'C':
                                                                case 'L':
                                                                case 'X':
                                                                case 'V':
                                                                case 'I':
                                                                    break;
                                                                default:
                                                                    valid = 0;
                                                            }
                                                
                                                            ++i;
                                                        }
                                                    }
                                                    else {
                                                        valid = 0;
                                                    }
                                                
                                                    return valid;
                                                }
                                                
                                                static int zrom_get_symbol_value(char symbol) {
                                                    switch (symbol) {
                                                        case 'M':
                                                            return 1000;
                                                        case 'D':
                                                            return 500;
                                                        case 'C':
                                                            return 100;
                                                        case 'L':
                                                            return 50;
                                                        case 'X':
                                                            return 10;
                                                        case 'V':
                                                            return 5;
                                                        case 'I':
                                                            return 1;
                                                        default:
                                                            return 0;
                                                    }
                                                }
                                                
                                                /* public functions ========================================================= */
                                                zrom_t * zrom_create(void) {
                                                    return calloc(1, sizeof (zrom_t));
                                                }
                                                
                                                void zrom_delete(zrom_t * zrom) {
                                                    free(zrom);
                                                }
                                                
                                                const char * zrom_get_string(const zrom_t * zrom) {
                                                    return zrom->string;
                                                }
                                                
                                                int zrom_get_value(const zrom_t * zrom) {
                                                    return zrom->value;
                                                }
                                                
                                                int zrom_set_string(zrom_t * zrom, const char * string) {
                                                    int error;
                                                
                                                    if (zrom_validate_string(string)) {
                                                        int i = 0;
                                                        
                                                        strcpy(zrom->string, string);
                                                
                                                        zrom->value = 0;
                                                
                                                        while (string[i]) {
                                                            int n = zrom_get_symbol_value(string[i]);
                                                
                                                            if (n < zrom_get_symbol_value(string[i + 1])) {
                                                                zrom->value -= n;
                                                            }
                                                            else {
                                                                zrom->value += n;
                                                            }
                                                
                                                            ++i;
                                                        }
                                                
                                                        error = 0;
                                                    }
                                                    else {
                                                        errno = EINVAL;
                                                        error =  -1;
                                                    }
                                                
                                                    return error;
                                                }
                                                
                                                int zrom_set_value(zrom_t * zrom, int value) {
                                                    int error;
                                                    
                                                    if (value > 0 && value < 4000) {
                                                        static const char * table[4][10] = {
                                                            {"", "M", "MM", "MMM"},
                                                            {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"},
                                                            {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"},
                                                            {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}
                                                        };
                                                        
                                                        zrom->value = value;
                                                
                                                        strcpy(zrom->string, table[0][value / 1000]);
                                                        value %= 1000;
                                                
                                                        strcat(zrom->string, table[1][value / 100]);
                                                        value %= 100;
                                                
                                                        strcat(zrom->string, table[2][value / 10]);
                                                        value %= 10;
                                                
                                                        strcat(zrom->string, table[3][value]);
                                                
                                                        error = 0;
                                                    }
                                                    else {
                                                        errno = EDOM;        
                                                        error =  -1;
                                                    }
                                                
                                                    return error;
                                                }
                                                
                                                void zrom_sanitize_string(zrom_t * zrom) {
                                                    zrom_set_value(zrom, zrom->value);
                                                }
                                                

                                                #include "zrom.h"
                                                
                                                #include <stdio.h>
                                                
                                                int main(void) {
                                                    zrom_t * zrom = zrom_create();
                                                
                                                    if (zrom_set_value(zrom, 42) == 0) {
                                                        printf("%s: %d\n", zrom_get_string(zrom), zrom_get_value(zrom));
                                                    }
                                                    else {
                                                        perror("zrom_set_value(zrom, 42)");
                                                    }
                                                
                                                    if (zrom_set_value(zrom, 0) == 0) {
                                                        printf("%s: %d\n", zrom_get_string(zrom), zrom_get_value(zrom));
                                                    }
                                                    else {
                                                        perror("zrom_set_value(zrom, 0)");
                                                    }
                                                
                                                    if (zrom_set_string(zrom, ZROM_LONGEST) == 0) {
                                                        printf("%s: %d\n", zrom_get_string(zrom), zrom_get_value(zrom));
                                                    }
                                                    else {
                                                        perror("zrom_set_string(zrom, ZROM_LONGEST)");
                                                    }
                                                
                                                    if (zrom_set_string(zrom, "MCMLXXXIV") == 0) {
                                                        printf("%s: %d\n", zrom_get_string(zrom), zrom_get_value(zrom));
                                                    }
                                                    else {
                                                        perror("zrom_set_string(zrom, \"MCMLXXXIV\")");
                                                    }
                                                
                                                    if (zrom_set_string(zrom, ZROM_LONGEST "I") == 0) {
                                                        printf("%s: %d\n", zrom_get_string(zrom), zrom_get_value(zrom));
                                                    }
                                                    else {
                                                        perror("zrom_set_string(zrom, ZROM_LONGEST \"I\")");
                                                    }
                                                
                                                    if (zrom_set_string(zrom, "VVIIIIVI") == 0) {
                                                        printf("%s: %d\n", zrom_get_string(zrom), zrom_get_value(zrom));
                                                    }
                                                    else {
                                                        perror("zrom_set_string(zrom, \"VVIIIIVI\")");
                                                    }
                                                
                                                    zrom_sanitize_string(zrom);
                                                    printf("%s: %d\n", zrom_get_string(zrom), zrom_get_value(zrom));
                                                
                                                    zrom_delete(zrom);
                                                
                                                    return 0;
                                                }
                                                


                                                Il faudrait que je peuple un peu mon jeu de test, mais à vue d'oeil ça passe.
                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  18 juin 2011 à 23:44:42

                                                  Citation : candide

                                                  Citation : joe78


                                                  itoa(nNb, pConv, 10);
                                                  




                                                  C'est portable ?

                                                  Non, ce n'est pas portable et pas standard.

                                                  Citation : candide


                                                  Citation : @che


                                                  int value[]  = {1000, 500, 100, 50, 10, 5, 1}; /* Les nombres correspondants aux chiffre romain */
                                                  char *digit = "MDCLXVI";                       /* Les chiffres romains par ordre décroissant */
                                                  


                                                  La position permet de passer de l'un a l'autre.



                                                  Oui mais c'est quand même très lourd un truc comme ça, un des défauts du C de ne pas avoir nativement des tableaux associatifs, je suppose qu'en C++ on n'a pas ce genre de lacune.

                                                  Pas plus qu'utiliser 256 cases o_O

                                                  Au pire en un tableau on peut faire :
                                                  int value[] = { 'M', 'D', 'C', 'L', 'X', 'V', 'I',1000, 500, 100, 50, 10, 5, 1};
                                                  Ou il suffit d'ajouter 7 pour avoir la valeur.

                                                  En C++ ils ont map je crois pour cela.
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter

                                                  🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.

                                                    19 juin 2011 à 11:07:10

                                                    Citation : candide


                                                    Oui mais je vois pas en quoi c'est un problème (tu peux très bien avoir des indices négatifs dans un tableau).



                                                    D'accord, mais c'est assez rare de voir des indices négatifs dans les tableaux, en général ça sent l'erreur, surtout si ce nombre négatif est obtenu suite au dépassement de la valeur maximale d'un type.
                                                    Maintenant, à bien y réfléchir, l'avertissement est sans doute plutôt dû à la taille variable d'un char (un byte, soit 8, 9, 15 (ou plus) octets bits :-° ).
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      19 juin 2011 à 12:03:06

                                                      Bonjour,

                                                      Citation : Twisted Destiny


                                                      Wow chapeau, l'implémentation de ton algo est vraiment astucieuse je trouve, en tout cas je n'en avais jamais vu une aussi simple...


                                                      Merci m'sieur ! :)
                                                      Moi j'aime bien ta fonction "romainVersArabe" qui à l'air super rapide (je ne l'ai pas testée en vrai, seulement de tête), surtout qu'elle gère le 0 de fin de chaîne sans cas particulier !
                                                      A froid, je ne vois pas non plus comment réduire le tableau de 256 cases sans faire au moins une passe sur la chaîne.

                                                      @ candide et @che :
                                                      Bon, apparement "atoi" n'a pas l'air de vous plaire.
                                                      On peut utiliser "snprintf" à la place, ça doit être plus portable (du moins ça fonctionne sur Windows et Linux). Ca vous irait ? :)

                                                      Clément.
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        19 juin 2011 à 12:11:29

                                                        Citation : joe78

                                                        @ candide et @che :
                                                        Bon, apparement "atoi" n'a pas l'air de vous plaire.
                                                        On peut utiliser "snprintf" à la place, ça doit être plus portable (du moins ça fonctionne sur Windows et Linux). Ca vous irait ? :)


                                                        Je vois pas trop pourquoi tu t'amuses à manipuler ton nombre à convertir sous forme d'une chaîne de caractères, avec un peu d'arithmétique élémentaire tu as le même résultat.

                                                        Jette un oeil à mon fonction zrom_set_value() pour voir de quoi je parle.

                                                        L'idéal ce serait de faire quelques tests et de voir les temps :p
                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          19 juin 2011 à 12:45:00

                                                          Bonjour,

                                                          Citation : MaitreZur


                                                          Je vois pas trop pourquoi tu t'amuses à manipuler ton nombre à convertir sous forme d'une chaîne de caractères, avec un peu d'arithmétique élémentaire tu as le même résultat.

                                                          Jette un oeil à mon fonction zrom_set_value() pour voir de quoi je parle.


                                                          Je préviens tout de suite que je ne veux pas lancer un débat ! :)

                                                          Pour répondre à ta question, je passe par ce subterfuge très spécifiquement pour ne pas avoir à écrire 4 lignes quasi-identiques comme tu l'as fait. Ca me permet aussi de ne faire que le nombre d'itérations nécessaire. (En plus ça m'évite aussi les modulos).

                                                          Mais encore une fois, ce n'est pas une critique.

                                                          Clément.
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            19 juin 2011 à 12:52:36

                                                            Citation : joe78

                                                            Je préviens tout de suite que je ne veux pas lancer un débat ! :)

                                                            Pour répondre à ta question, je passe par ce subterfuge très spécifiquement pour ne pas avoir à écrire 4 lignes quasi-identiques comme tu l'as fait. Ca me permet aussi de ne faire que le nombre d'itérations nécessaire. (En plus ça m'évite aussi les modulos).


                                                            Ce n'est pas non plus mon intention de lancer un débat :p

                                                            Je comprends mieux, c'est juste que ça me semblait peu naturel. En fait tu délègues juste "les modulos" à itoa(), c'est vrai que finalement ça revient au même.
                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                              19 juin 2011 à 13:04:08

                                                              Exo sympathique, voilà ce que je propose (pour les 2 premiers exos pour l'instant) :

                                                              Exercice 1 :

                                                              typedef struct Valeur Valeur;
                                                              struct Valeur{
                                                                  char lettre;
                                                                  int value;
                                                              };
                                                              
                                                              int RomToArab(char *rom){
                                                                  int i=strlen(rom)-1,arab=0,j=0,prec=0;
                                                                  Valeur val[7]={{'I',1},{'V',5},{'X',10},{'L',50},{'C',100},{'D',500},{'M',1000}};
                                                                  while(i>=0){
                                                                      j=0;
                                                                      while(rom[i]!=val[j].lettre) j++;
                                                                      prec=val[j].value<prec ? -val[j].value : val[j].value;
                                                                      arab+=prec;
                                                                      i--;
                                                                  }
                                                                  return arab;
                                                              }
                                                              



                                                              Exercice 2 :

                                                              typedef struct Valeur Valeur;
                                                              struct Valeur{
                                                                  char lettre;
                                                                  int value;
                                                              };
                                                              
                                                              void ArabToRom(int arab, char* rom){
                                                                  int i=6,div=0,j=0;
                                                                  Valeur val[7]={{'I',1},{'V',5},{'X',10},{'L',50},{'C',100},{'D',500},{'M',1000}};
                                                                  while(i>=0){
                                                                      div=arab/val[i].value;
                                                                      if(div==4){
                                                                          rom[j++]=val[i].lettre;
                                                                          rom[j++]=val[i+1].lettre;
                                                                          arab-=val[i+1].value-val[i].value;
                                                                      }
                                                                      else if(div!=0){
                                                                          while(div-->0){
                                                                              rom[j++]=val[i].lettre;
                                                                              arab-=val[i].value;
                                                                          }
                                                                      }
                                                                      i--;
                                                                  }
                                                              }
                                                              


                                                              J'ai juste mis les fonctions de conversion.
                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              zRom

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                              • Editeur
                                                              • Markdown