Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Exercices] Venez vous entraîner !

(v2)

    2 juillet 2011 à 22:13:48

    non lol je veux dire es-ce que la nouvelle norme est intéressante ou pas ? Vaut-elle l'apprendre quand on débute ou non ?
    • Partager sur Facebook
    • Partager sur Twitter
      3 juillet 2011 à 0:48:07

      Quand on débute, la lecture d'un document comme celui-ci peut décourager, non ? 1320 pages de description du C++.

      Sinon, je viens de faire l'exercice du chiffre de césar, je me sens particulièrement content du cassage (réussit à casser même des messages dont les e ont été remplacés par des *, ce que d'autres ne permettent pas, cf. le commentaire dans cesar.cpp).
      Le code (à nouveau un peu de c++11, particulièrement shared_ptr) :

      #include <cstdlib>
      #include <iostream>
      #include <fstream>
      #include <memory>
      #include <vector>
      #include <sstream>
      #include <string>
      
      #include "cesar.hpp"
      
      void usage(std::string nom_prog = "cesar")
      {
          std::cerr <<
              "Usage : " <<
              nom_prog <<
              " [-k[ey] KEY]"
              " { -c[rypt] | -d[ecrypt] | -b[reak] }"
              " { FILE_IN | - } { FILE_OUT | - }"
              << std::endl;
      }
      
      short getKey(const std::vector<std::string> & args)
      {
          for (std::size_t i = 0 ; i < args.size() - 1 ; ++i) {
              if (args[i][0] == '-' && args[i][1] == 'k') {
                  std::istringstream iss(args[i + 1]);;
                  short key;
                  iss >> key;
                  return key;
              }
          }
          return 0;
      }
      
      char getAction(const std::vector<std::string> & args)
      {
          std::string allowed("cdb");
          for (std::size_t i = 0 ; i < args.size() ; ++i) {
              if (args[i][0] == '-' && allowed.find_first_of(args[i][1]) != std::string::npos) {
                  return args[i][1];
              }
          }
          return '?';
      }
      
      static void useless() {} 
      
      typedef std::shared_ptr<std::istream> Istr;
      typedef std::shared_ptr<std::ostream> Ostr;
      
      static void NoOpDeleter(void *) { }
      
      std::pair<Istr, Ostr> getStreams(const std::vector<std::string> & args)
      {
          std::string inS("-"), outS("-");
          if (args.size() >= 3 && args[args.size() - 2][0] != '-') {
              inS = args[args.size() - 2];
              outS = args.back();
          } else if (args.size() >= 2 && args.back()[0] != '-') {
              inS = args.back();
          }
          Istr in;
          if (inS == "-") {
              in.reset(&std::cin, NoOpDeleter);
          } else {
              in.reset(new std::ifstream(inS));
          }
          Ostr out;
          if (outS == "-") {
              out.reset(&std::cout, NoOpDeleter);
          } else {
              out.reset(new std::ofstream(outS));
          }
          return std::make_pair(in, out);
      }
      
      int main(int argc, char** argv)
      {
          if (argc < 1) {
              usage();
              return EXIT_FAILURE;
          }
      
      #define FAIL \
          usage(argv[0]); \
          return EXIT_FAILURE
      
      #define ASSERT(Cond) \
          if (!(Cond)) { \
              FAIL; \
          } \
          useless()
      
          std::vector<std::string> args;
          for (int arg = 0 ; arg < argc ; ++arg) {
              args.push_back(argv[arg]);
          }
      
          char action = getAction(args);
          ASSERT(action != '?');
      
          short key = getKey(args);
          if (action == 'c' || action == 'd') {
              ASSERT(key != 0);
          }
      
          std::pair<Istr, Ostr> streams = getStreams(args);
          Istr in  = streams.first;
          Ostr out = streams.second;
      
          if (action == 'd') {
              key = -key;
          }
      
          if (action == 'b') {
              std::string s, tmp;
              while (in->good()) {
                  std::getline(*in, tmp);
                  s += tmp + "\n";
              }
              std::pair<std::string, short> res = cesar::crack(s);
              *out << res.first << std::endl;
              *out << "==================================================" << std::endl;
              *out << "Decalage : " << res.second << std::endl;
          } else {
              std::string tmp;
              while (in->good()) {
                  std::getline(*in, tmp);
                  *out << cesar::crypt(tmp, key) << std::endl;
              }
          }
          return EXIT_SUCCESS;
      }
      

      #ifndef CESAR_HPP_INCLUDED
      #define CESAR_HPP_INCLUDED
      
      #include <string>
      #include <utility>
      
      namespace cesar
      {
          extern const double Frequencies_FR[];
      
          std::string   crypt(const std::string & s, short k);
          std::string decrypt(const std::string & s, short k);
      
          /**
           * Tente de casser le cryptage de cesar
           *
           * @param s la chaine a tenter de casser
           * @param freq le tableau de frequences a utiliser (francais par defaut)
           * @return la chaine decryptee la plus probable
           *
           * @author Equinoxe
           */
          std::pair<std::string, int> crack(
              const std::string & s,
              const double * freq = Frequencies_FR
          );
      }
      
      #endif // CESAR_HPP_INCLUDED
      

      #include "cesar.hpp"
      
      #include <cmath>
      #include <string>
      #include <limits>
      #include <locale>
      
      static char mod(char a, int m) {
          while (a < 0) a += m;
          a %= m;
          return a;
      }
      
      static char docrypt(char c, short k)
      {
          if (std::isupper(c)) return mod((c - 'A' + k), 26) + 'A';
          if (std::islower(c)) return mod((c - 'a' + k), 26) + 'a';
          if (std::isdigit(c)) return mod((c - '0' + k), 10) + '0';
          return c;
      }
      
      namespace cesar
      {
          const double Frequencies_FR[] =
          {
              9.42, 1.02, 2.64, 3.39, 15.87, 0.95, 1.04, 0.77, 8.41,
              0.89, 0.00, 5.34, 3.24,  7.15, 5.14, 2.86, 1.06, 6.46,
              7.90, 7.26, 6.24, 2.15,  0.00, 0.30, 0.24, 0.32
          }; // Thanks Wikipedia FR !
      
          std::string crypt(const std::string & s, short k)
          {
              std::string res(s.length(), ' ');
              for (size_t i = 0; i < s.length(); ++i)
                  res[i] = docrypt(s[i], k);
              return res;
          }
          std::string decrypt(const std::string & s, short k)
          {
              return crypt(s, -k);
          }
      
          /**
           * Tente de casser le cryptage de cesar
           *
           * Complexite :
           * o N <- longueur(s)
           * o L <- taille_de_l_alphabet
           * complexite = O(2N + 2L + L²) = O(N+L²)
           * Avec un alphabet restreint (L² << N), cela donne O(N), ce qui est le
           * meilleur resultat possible. Pour un texte francais (alphabet de 26
           * lettres), cela donne O(700 + N) ~= O(N) (En considerant un long
           * texte).
           *
           * Cependant, cette methode de decryptage permet de casser avec un grand
           * taux de reussite :
           * "Le zebre et le yeti mangent des chamallows et des yaourts dans le
           *     wagon."
           * devient, crypte avec un chiffre de 14 :
           * "Zs nspfs sh zs mshw aobusbh rsg qvoaozzckg sh rsg mocifhg robg zs
           *     koucb."
           * Et peut etre casse, malgre les lettres peu courantes.
           * De meme pour : "L'*x*rcic* m'int*r*ss*" (les e sont caches par des *,
           * ce qui gene le cassage par analyse frequentielle que nous utilisons).
           *
           * @param s la chaine a tenter de casser
           * @param freq le tableau de frequences a utiliser (francais par defaut)
           * @return la chaine decryptee la plus probable et la clef ayant permis
           *         de casser
           *
           * @author Equinoxe
           * @todo Proposer a l'utilisateur de prendre une autre chaine resultat,
           *       voire un tableau des 26 resultats possibles, trié par ordre de
           *       probabilite ?
           */
          std::pair<std::string, int> crack(const std::string & s, const double * freq)
          {
              /*
               D'abord, calculer le nombre d'apparitions de chaque lettre et le
               nombre de caractere non speciaux
              */
              size_t apparitions[26] = {0};
              size_t size = 0;
              for (size_t i = 0; i < s.length(); ++i)
              {
                  if (isupper(toupper(s[i])))
                  {
                      ++apparitions[toupper(s[i]) - 'A'];
                      ++size;
                  }
              }
              /*
               Ensuite, calculer les frequences de chaque lettre
              */
              double frequences[26] = {0.};
              for (short i = 0; i < 26; ++i)
              {
                  frequences[i] = apparitions[i] * 100. / size;
              }
              /*
               Ensuite, calculer la distance par rapport au tableau de frequences
               donne en parametre
              */
              double probabilites[26] = {0.};
              for (short k = 0; k < 26; ++k)
              {
                  for (char c = 'A'; c <= 'Z'; ++c)
                  {
                      probabilites[k] += std::abs(
                                              frequences[
                                                  docrypt(c, -k) - 'A'
                                              ]
                                             -
                                              freq[c - 'A']
                                         );
                  }
              }
              /*
               Enfin, trouver le meilleur decryptage possible
              */
              size_t decalage = 0;
              double min = std::numeric_limits<double>::max();
              for (short i = 0; i < 26; ++i)
              {
                  if (probabilites[i] < min)
                  {
                      min = probabilites[i];
                      decalage = i;
                  }
              }
              // Et renvoyer le resultat decrypte par le decalage le plus probable
              return std::make_pair(crypt(s, decalage), 26 - decalage);
          }
      }
      


      Qu'en pensez-vous ?
      Pensez-vous qu'il serait intéressant de mettre ma version du cassage en solution, étant donné qu'elle est plus performante que celle proposée par la solution actuelle ?
      • Partager sur Facebook
      • Partager sur Twitter
        3 juillet 2011 à 1:20:43

        à mon avis, dans un programme si léger, c'est pas trop grave si je perd 1/16 de sec (ou surement bien moins ;) )
        • Partager sur Facebook
        • Partager sur Twitter
          3 juillet 2011 à 9:41:01

          Citation : Equinoxe

          Euh ... C'est-à-dire que ... En fait ... Bah ...
          C'est une assiette de morpion !
          En fait, si on veut être précis, ce que je dessine c'est une plaque.
          Parce que, après tout, il n'y a pas de champ de morpion. :p


          Si, field = terrain. (ici de jeu)
          • Partager sur Facebook
          • Partager sur Twitter
            3 juillet 2011 à 11:07:33

            Est-ce que la dénomination est vraiment importante ?

            Parce que je dois admettre que j'avais commencé à coder en français, et que, parce que finalement je préférais l'anglais, j'ai cherché à modifier le programme en en faisant le moins possible. Du coup, j'ai juste cherché un mot proche, sans me soucier de la traduction finale.

            Et, pour le cas, mon message précédent était une maigre tentative d'humour.
            • Partager sur Facebook
            • Partager sur Twitter
              3 juillet 2011 à 11:26:19

              non je suis pas d'accord, je vote pour la peine capitale :pirate::colere::diable:

              euuuh ... en fait on s'en fout non ?
              • Partager sur Facebook
              • Partager sur Twitter
                3 juillet 2011 à 12:13:15

                ^^ (à ce propos, c'est CanPlay et pas MayPlay dans ce cas)
                • Partager sur Facebook
                • Partager sur Twitter
                  3 juillet 2011 à 12:39:31

                  Là, j'en suis sûr, j'avais commencé par mettre CanPlay avant de réfléchir.
                  En effet, on ne demande pas si on a la capacité de jouer (ce qui est toujours le cas : un utilisateur peut toujours appuyer sur les boutons qu'il veut), mais si on a le droit de jouer, suivant les règles du jeu.
                  Donc c'est bien MayPlay.
                  Fail. :p

                  Edit :
                  D'ailleurs, pour les notes de difficulté, je propose un pour TicTacToe, trois pour le chiffre de césar (deux plus un de cassage), quatre pour le chiffre de vigénère (Le cassage est particulièrement tordu), et deux pour le cryptage XOR, parce qu'il n'y a que cryptage/décryptage à gérer.
                  • Partager sur Facebook
                  • Partager sur Twitter
                    3 juillet 2011 à 13:05:41

                    oui en effet commencer à mettre les difficultés serait pratique pour ceux qui voudrait commencer les exos mais qui ne savent pas par ou commencer.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      3 juillet 2011 à 14:25:31

                      La question que je posais était surtout sur votre avis par rapport aux notes que je propose, sachant que la note de difficulté maximale prévue est 5.
                      • Partager sur Facebook
                      • Partager sur Twitter
                        3 juillet 2011 à 14:28:42

                        je ne connait pas tout les exos en détail et je ne les ai pas encore essayer donc je peut pas trop dire (à part pour le Tic-Tac-Toe qui est facile)
                        • Partager sur Facebook
                        • Partager sur Twitter
                          3 juillet 2011 à 17:17:03

                          Citation : Equinoxe

                          Là, j'en suis sûr, j'avais commencé par mettre CanPlay avant de réfléchir.
                          En effet, on ne demande pas si on a la capacité de jouer (ce qui est toujours le cas : un utilisateur peut toujours appuyer sur les boutons qu'il veut), mais si on a le droit de jouer, suivant les règles du jeu.
                          Donc c'est bien MayPlay.
                          Fail. :p

                          Edit :
                          D'ailleurs, pour les notes de difficulté, je propose un pour TicTacToe, trois pour le chiffre de césar (deux plus un de cassage), quatre pour le chiffre de vigénère (Le cassage est particulièrement tordu), et deux pour le cryptage XOR, parce qu'il n'y a que cryptage/décryptage à gérer.


                          1) C'est can. désolé :p !
                          une fonction qui s'appelle mayPlay devrait retourner la probabilité que l'on joue ici.
                          Ou bien alors c'est que tu es vraiment trop poli pour un programmeur quand tu demandes la permission.
                          Can = capacité / Autorisation
                          (ex: Can I have a shower ?)

                          2)Pour les difficultés : je vais regarder de plus près les exercices en question...
                          • Partager sur Facebook
                          • Partager sur Twitter
                            3 juillet 2011 à 21:38:03

                            J'ai fini l'exercice du chiffre de vigénère, il est vraiment compliqué de trouver les formules pour la longueur de la clef (bon, pour la recherche de la clef elle-même, ce n'est pas plus dur que le chiffre de césar).
                            Je maintiens donc 4 de difficulté.

                            Ma solution (encore améliorable, j'ai juste fait quelque chose de fonctionnel) :
                            main.cpp :
                            #include "Vigenere.hpp"
                            
                            #include <fstream>
                            #include <iostream>
                            #include <map>
                            #include <memory>
                            #include <sstream>
                            #include <string>
                            
                            typedef std::map<std::string, std::string> option_map;
                            
                            void parseOpts(option_map & map, int argc, char** argv);
                            
                            bool hasOpt(const option_map & map, const std::string & opt) {
                                return map.find(opt) != map.end();
                            }
                            std::string & getOpt(option_map & map, const std::string & opt) {
                                return map[opt];
                            }
                            
                            typedef std::shared_ptr<std::istream> Istr;
                            typedef std::shared_ptr<std::ostream> Ostr;
                            
                            void NoOpDeleter(void *) {}
                            Istr inStr(const std::string & str) {
                                if (str == "-") {
                                    return Istr(&std::cin, NoOpDeleter);
                                } else {
                                    return Istr(new std::ifstream(str));
                                }
                            }
                            Ostr outStr(const std::string & str) {
                                if (str == "-") {
                                    return Ostr(&std::cout, NoOpDeleter);
                                } else {
                                    return Ostr(new std::ofstream(str));
                                }
                            }
                            
                            enum class Action { Unknown, Crypt, Decrypt, Crack };
                            
                            void usage(const std::string & prog = "vigenere")
                            {
                                std::cerr <<
                                    "Usage : " << prog <<
                                    " [ -k KEY ]" <<
                                    " { -c | -d }" <<
                                    " [ -i { FILE_IN | - } ]" <<
                                    " [ -o { FILE_OUT | - } ]" <<
                                    std::endl;
                                std::cerr <<
                                    "-c : Crypt" << std::endl <<
                                    "-d : Decrypt" << std::endl <<
                                    "-b : Break without the key." << std::endl <<
                                    "     Then the key could whether be an integer," << std::endl <<
                                    "     the known length of the key, whether be" << std::endl <<
                                    "     absent." << std::endl <<
                                    std::endl <<
                                    "-i : Input from the file FILE_IN, or from standard" << std::endl <<
                                    "     input, if '-' is provided. Default '-'." << std::endl <<
                                    "-o : Output to the file FILE_OUT, or to standard" << std::endl <<
                                    "     output, if '-' is provided. Default '-'." << std::endl <<
                                    std::endl <<
                                    "-k : The key with which cipher. Only alphabetic" << std::endl <<
                                    "     characters should be placed, otherwise the" << std::endl <<
                                    "     result is undefined. If -b is provided, then" << std::endl <<
                                    "     it could whether represent the length of the" << std::endl <<
                                    "     key, whether be absent. However, it is" << std::endl <<
                                    "     compulsory with -c or -d." << std::endl <<
                                    std::endl;
                            }
                            
                            #define FAIL \
                                usage (argv[0]); \
                                return EXIT_FAILURE
                            
                            #define ASSERT(C) \
                                if (!(C)) { \
                                    FAIL; \
                                }
                            
                            int main(int argc, char** argv)
                            {
                                if (argc < 1) {
                                    usage();
                                    return EXIT_FAILURE;
                                }
                            
                                option_map map;
                                parseOpts(map, argc, argv);
                            
                                Action action = Action::Unknown;
                                if (hasOpt(map, "-c")) {
                                    action = Action::Crypt;
                                    ASSERT(!hasOpt(map, "-d") && !hasOpt(map, "-b"));
                                } else if (hasOpt(map, "-d")) {
                                    action = Action::Decrypt;
                                    ASSERT(!hasOpt(map, "-b"));
                                } else if (hasOpt(map, "-b")) {
                                    action = Action::Crack;
                                }
                                ASSERT(action != Action::Unknown);
                            
                                std::string key = getOpt(map, "-k");
                                ASSERT(action == Action::Crack || key != "");
                            
                                std::string  inS = getOpt(map, "-i");
                                if ( inS == "")  inS = "-";
                                std::string outS = getOpt(map, "-o");
                                if (outS == "") outS = "-";
                            
                                Istr  in =  inStr( inS);
                                Ostr out = outStr(outS);
                            
                                Vigenere V(key);
                                if (action != Action::Crack) {
                                    while (in->good()) {
                                        std::string tmp;
                                        std::getline(*in, tmp);
                                        if (action == Action::Crypt) {
                                            *out << V.Crypt(tmp) << std::endl;
                                        } else if (action == Action::Decrypt) {
                                            *out << V.Decrypt(tmp) << std::endl;
                                        }
                                    }
                                } else {
                                    std::string s;
                                    while (in->good()) {
                                        std::string tmp;
                                        std::getline(*in, tmp);
                                        s += tmp + "\n";
                                    }
                                    int keyLen = -1;
                                    if (key != "") {
                                        std::istringstream iss(key);
                                        iss >> keyLen;
                                    }
                                    std::pair<std::string, std::string> result = V.Crack(s, keyLen);
                                    *out << result.first;
                                    std::cout << "=================================================="
                                              << std::endl
                                              << "Key : " << result.second << std::endl;
                                }
                            
                                return EXIT_SUCCESS;
                            }
                            
                            void parseOpts(option_map & map, int argc, char** argv)
                            {
                                for (int argi = 1 ; argi < argc ; argi += 2) {
                                    std::string arg = argv[argi];
                                    std::string value = "";
                                    if (argi + 1 < argc) {
                                        std::string nextArg = argv[argi + 1];
                                        if (nextArg[0] != '-') {
                                            value = nextArg;
                                        } else {
                                            --argi;
                                        }
                                    }
                                    map.insert(std::make_pair(arg, value));
                                }
                            }
                            

                            Vigenere.hpp :
                            #ifndef VIGENERE_HPP_INCLUDED__
                            #define VIGENERE_HPP_INCLUDED__ 1
                            
                            #include <string>
                            #include <vector>
                            
                            struct Vigenere {
                                static const double Frequencies_FR[];
                                static const double IC_FR;
                                static const std::vector<std::string> Dict_FR;
                            
                                Vigenere(const std::string key)
                                    : st_(0), key_(key)
                                { }
                            
                                std::string Crypt(const std::string & s);
                                std::string Decrypt(const std::string & s);
                            
                                /**
                                 * TODO : Use Dict_FR, allow for errors and seek through the entire
                                 * answers.
                                 */
                                std::pair<std::string, std::string> Crack(
                                        const std::string & s,
                                        int keyLen = -1,
                                        const std::vector<std::string> & Dict = Dict_FR,
                                        const double * Frequencies = Frequencies_FR,
                                        const double IC = IC_FR
                                        );
                            
                            private:
                                size_t st_;
                                std::string key_;
                            };
                            
                            #endif
                            

                            Vigenere.cpp :
                            #include "Vigenere.hpp"
                            
                            #include <algorithm>
                            #include <cmath>
                            #include <limits>
                            #include <vector>
                            #include <string>
                            
                            #include <iostream>
                            
                            const double Vigenere::Frequencies_FR[] =
                            {
                                9.42, 1.02, 2.64, 3.39, 15.87, 0.95, 1.04, 0.77, 8.41,
                                0.89, 0.00, 5.34, 3.24,  7.15, 5.14, 2.86, 1.06, 6.46,
                                7.90, 7.26, 6.24, 2.15,  0.00, 0.30, 0.24, 0.32
                            }; // Thanks Wikipedia FR !
                            const double Vigenere::IC_FR = .0778; // Thanks bis !
                            const std::vector<std::string> Vigenere::Dict_FR {
                                "je", "tu", "il", "on", "le", "la", "ce", "ca",
                                "ou", "et", "ma", "sa", "ta",
                                "do", "re", "mi", "fa", "so", "la", "si",
                                "qu", "ex", "al", "an", "en"
                            };
                            
                            static char mod_(char c, short m) {
                                while (c < 0) c += m;
                                c %= m;
                                return c;
                            }
                            static char crypt_(char c, char k) {
                                return mod_(c - 'A' + k, 26) + 'A';
                            }
                            static char decrypt_(char c, char k) {
                                return crypt_(c, -k);
                            }
                            
                            std::string Vigenere::Crypt(const std::string & s) {
                                std::string ret(s.length(), ' ');
                                for (size_t i = 0 ; i < s.length() ; ++i) {
                                    if (std::isupper(std::toupper(s[i]))) {
                                        ret[i] = crypt_(
                                                std::toupper(s[i]),
                                                std::toupper(key_[st_]) - 'A'
                                                );
                                        st_ = (st_ + 1) % key_.length();
                                        if (std::islower(s[i]))
                                            ret[i] = std::tolower(ret[i]);
                                    } else {
                                        ret[i] = s[i];
                                    }
                                }
                                return ret;
                            }
                            
                            std::string Vigenere::Decrypt(const std::string & s) {
                                std::string ret(s.length(), ' ');
                                for (size_t i = 0 ; i < s.length() ; ++i) {
                                    if (std::isupper(std::toupper(s[i]))) {
                                        ret[i] = decrypt_(
                                                std::toupper(s[i]),
                                                std::toupper(key_[st_]) - 'A'
                                                );
                                        st_ = (st_ + 1) % key_.length();
                                        if (std::islower(s[i]))
                                            ret[i] = std::tolower(ret[i]);
                                    } else {
                                        ret[i] = s[i];
                                    }
                                }
                                return ret;
                            }
                            
                            static int estimate_key_len_(
                                    const std::string & s,
                                    const double IC_language
                                    );
                            
                            std::pair<std::string, std::string> Vigenere::Crack(
                                    const std::string & s,
                                    int len,
                                    const std::vector<std::string> & Dict,
                                    const double * freq,
                                    const double IC
                                    ) {
                                if (len < 0) {
                                    len = estimate_key_len_(s, IC);
                                }
                                std::vector<std::string> strings(len);
                                for (size_t i = 0, ki = 0 ; i < s.length() ; ++i) {
                                    if (std::isupper(std::toupper(s[i]))) {
                                        strings[ki].push_back(std::toupper(s[i]));
                                        ki = (ki + 1) % len;
                                    }
                                }
                                std::string key;
                                for (size_t iS = 0 ; iS < len ; ++iS) {
                                    std::string & str = strings[iS];
                                    size_t appears[26] = {0};
                                    for (size_t i = 0 ; i < str.length() ; ++i) {
                                        ++appears[str[i] - 'A'];
                                    }
                                    double frequencies[26] = {0.};
                                    for (short i = 0 ; i < 26 ; ++i) {
                                        frequencies[i] = appears[i] * 100. / str.length();
                                    }
                                    double probabilities[26] = {0.};
                                    for (short k = 0 ; k < 26 ; ++k) {
                                        for (char c = 'A' ; c <= 'Z' ; ++c) {
                                            probabilities[k] += std::abs(
                                                                    frequencies[crypt_(c, k) - 'A']
                                                                -
                                                                    freq[c - 'A']
                                                                    );
                                        }
                                    }
                                    short index = 0;
                                    double min = std::numeric_limits<double>::max();
                                    for (short i = 0 ; i < 26 ; ++i) {
                                        if (probabilities[i] < min) {
                                            min = probabilities[i];
                                            index = i;
                                        }
                                    }
                                    key.push_back(index + 'A');
                                }
                                Vigenere V(key);
                                return std::make_pair(V.Decrypt(s), key);
                            }
                            
                            static double ic(const std::string & s);
                            static bool ic_sufficient_(double IC, const double IC_language);
                            
                            static int estimate_key_len_(const std::string & s, const double IC_language)
                            {
                                std::string str(s.length(), ' ');
                                size_t w = 0;
                                for (char c : s) {
                                    if (std::isupper(std::toupper(c))) {
                                        str[w++] = std::toupper(c);
                                    }
                                }
                                str.resize(w);
                                std::vector<double> ICs;
                                for (size_t l = 1 ; l < s.length() ; ++l) {
                                    std::vector<std::string> strings(l);
                                    size_t i = size_t(-1); // So that first value is 0
                                    for (char c : str) strings[++i %= l].push_back(c);
                                    double IC = 0;
                                    for (std::string & ss : strings) IC += ic(ss);
                                    if (ic_sufficient_(IC / l, IC_language)) return l;
                                    ICs.push_back(IC);
                                }
                                return std::max(std::begin(ICs), std::end(ICs)) - std::begin(ICs) + 1;
                            }
                            
                            static double ic(const std::string & s)
                            {
                                size_t counts[26] = {0};
                                for (char c : s) ++counts[c - 'A'];
                                double answer = 0.;
                                for (short i = 0 ; i < 26 ; ++i) answer += counts[i] * (counts[i] - 1);
                                return answer / (s.length() * (s.length() - 1));
                            }
                            
                            static bool ic_sufficient_(double IC, const double IC_language)
                            {
                                return IC > IC_language * .9;
                            }
                            


                            Edit : En moins d'une heure je viens de faire le XOR (preuve qu'il est plus facile) :
                            main.cpp :
                            #include <iostream>
                            #include <memory>
                            
                            #include "../OptionMap.hpp"
                            #include "../Streams.hpp"
                            
                            void usage(const std::string & prog)
                            {
                                std::cout <<
                                    "Usage : " << prog <<
                                    " -k KEY" <<
                                    " [ -i { IN_FILE | - } ]" <<
                                    " [ -o { OUT_FILE | - } ]" <<
                                    std::endl;
                            }
                            
                            int main(int argc, char** argv)
                            {
                                OptionMap options(argc, argv);
                            
                                std::string key = options.get("-k");
                                if (key == "") {
                                    usage(options.prog());
                                    return EXIT_FAILURE;
                                }
                                size_t ki = 0;
                            
                                Istr  in =  inputStream(options.get("-i", "-"));
                                Ostr out = outputStream(options.get("-o", "-"));
                            
                                char buffer[512];
                                while (in->good()) {
                                    in->read(buffer, 512);
                                    for (size_t i = 0 ; i < in->gcount() ; ++i) {
                                        buffer[i] = buffer[i] ^ key[ki];
                                        ki = (ki + 1) % key.length();
                                    }
                                    out->write(buffer, in->gcount());
                                }
                            
                                return EXIT_SUCCESS;
                            }
                            

                            ../OptionMap.hpp :
                            #ifndef OPTIONMAP_HPP_INCLUDED__
                            #define OPTIONMAP_HPP_INCLUDED__ 1
                            
                            #include <map>
                            
                            class OptionMap
                            {
                            public:
                                OptionMap(int const argc, char const * const * const argv);
                            
                                std::string prog() const;
                            
                                bool has(const std::string & opt) const;
                                std::string get(const std::string & opt, const std::string & Default = "") const;
                            
                                template <typename T>
                                    T as(const std::string & opt);
                            
                                void load(int const argc, char const * const * const argv);
                            
                            private:
                                typedef std::map<std::string, std::string> map_type;
                                
                                map_type map_;
                                std::string prog_;
                            };
                            
                            // ============================IMPLEMENTATION=============================
                            
                            #include <sstream>
                            
                            inline OptionMap::OptionMap(int const argc, char const * const * const argv)
                            {
                                load(argc, argv);
                            }
                            
                            inline bool OptionMap::has(const std::string & opt) const
                            {
                                return map_.find(opt) != map_.end();
                            }
                            
                            inline std::string OptionMap::prog() const
                            {
                                return prog_;
                            }
                            
                            inline std::string OptionMap::get(
                                    const std::string & opt,
                                    const std::string & Default
                                    ) const {
                                map_type::const_iterator it = map_.find(opt);
                                if (it == map_.end()) {
                                    return Default;
                                } else {
                                    return it->second;
                                }
                            }
                            
                            template <typename T>
                            inline T OptionMap::as(const std::string & opt)
                            {
                                std::string val = get(opt);
                            
                                if (val == "") return T();
                            
                                std::istringstream iss(val);
                                T t;
                                iss >> t;
                                return t;
                            }
                            
                            inline void OptionMap::load(int const argc, char const * const * const argv)
                            {
                                prog_ = argv[0];
                                for (int argi = 1 ; argi < argc ; argi += 2) {
                                    std::string arg = argv[argi];
                                    std::string value = "";
                                    if (argi + 1 < argc) {
                                        std::string nextArg = argv[argi + 1];
                                        if (nextArg[0] != '-') {
                                            value = nextArg;
                                        } else {
                                            --argi;
                                        }
                                    }
                                    map_.insert(std::make_pair(arg, value));
                                }
                            }
                            
                            #endif
                            

                            ../Streams.hpp :
                            #ifndef STREAMS_HPP_INCLUDED__
                            #define STREAMS_HPP_INCLUDED__ 1
                            
                            #include <fstream>
                            #include <iostream>
                            #include <memory>
                            
                            typedef std::shared_ptr<std::istream> Istr;
                            typedef std::shared_ptr<std::ostream> Ostr;
                            
                            Istr  inputStream(const std::string &);
                            Ostr outputStream(const std::string &);
                            
                            // =======================IMPLEMENTATION=====================
                            
                            void streams_NoOpDeleter(void *) {}
                            
                            inline Istr inputStream(const std::string & s)
                            {
                                if (s == "-") {
                                    return Istr(&std::cin, &streams_NoOpDeleter);
                                } else {
                                    return Istr(new std::ifstream(s));
                                }
                            }
                            
                            inline Ostr outputStream(const std::string & s)
                            {
                                if (s == "-") {
                                    return Ostr(&std::cout, &streams_NoOpDeleter);
                                } else {
                                    return Ostr(new std::ofstream(s));
                                }
                            }
                            
                            #endif
                            


                            Edit2 : Le Cowsay est plutôt simple aussi, je le mettrais à un et demi. N'empêche qu'il faudrait au moins une autre personne qui se dise d'accord (ou pas) avec moi, que je commence à mettre les notes de difficulté. ^^
                            main.cpp :
                            #include <iostream>
                            #include <string>
                            #include <vector>
                            
                            const int MAX_CHAR = 50;
                            
                            const std::string IMAGE =
                            "       \\   ^__^\n"
                            "        \\  (oo)\\_______\n"
                             "           (__)\\       )\\/\\\n"
                             "               ||----W |\n"
                             "               ||     ||\n";
                            
                            int main(int argc, char ** argv)
                            {
                                std::string str;
                                for (int argi = 1 ; argi < argc ; ++argi) {
                                    str += argv[argi];
                                    str += " ";
                                }
                                str.resize(str.size() - 1);
                            
                                std::vector<std::string> lines;
                                for (size_t i = 0 ; i < str.length() ; ++i) {
                                    if (i + MAX_CHAR >= str.length()) {
                                        lines.push_back(str.substr(i));
                                        break;
                                    }
                                    size_t j = str.find_last_of(" \t\n", i + MAX_CHAR);
                                    if (j == std::string::npos || j <= i) {
                                        lines.push_back(str.substr(i, MAX_CHAR));
                                        i += MAX_CHAR;
                                    } else {
                                        lines.push_back(str.substr(i, j - i));
                                        i = j;
                                    }
                                }
                            
                                size_t maxLen = 0;
                                for (std::string & s : lines)
                                    if (s.length() > maxLen)
                                        maxLen = s.length();
                            
                                std::string sep(maxLen + 2, '-');
                            
                                std::cout << "/" << sep << "\\" << std::endl;
                                for (std::string & s : lines) {
                                    std::cout << "| " << s;
                                    for (size_t i = s.length() ; i < maxLen ; ++i) {
                                        std::cout << " ";
                                    }
                                    std::cout << " |" << std::endl;
                                }
                                std::cout << "\\" << sep << "/" << std::endl;
                                std::cout << IMAGE << std::endl;
                            
                                return EXIT_SUCCESS;
                            }
                            
                            • Partager sur Facebook
                            • Partager sur Twitter
                              4 juillet 2011 à 10:41:15

                              Pour le cowsay il est pas si simple que ça : je ne sais pas si t'as vu le nombre d'entités de la STL que tu as employée... je dirais au moins 2.
                              Pour Vigénère, t'as raison :)
                              XOR 3, c'est parfait.
                              • Partager sur Facebook
                              • Partager sur Twitter
                                4 juillet 2011 à 11:16:46

                                C'est vrai que, du coup, je dirais environ ausi dur que le chiffre de césar.

                                Donc, on récapitule les difficultés avant de mettre :
                                - Cesar : 3
                                - Vigénère : 4
                                - XOR : 3
                                - Cowsay : 2, deux et demi ?
                                • Partager sur Facebook
                                • Partager sur Twitter
                                  4 juillet 2011 à 11:54:42

                                  Pas de demi, sinon on va se retrouver avec des quarts et des huitièmes, ce sera le bazar.
                                  ok.
                                  Pour le Cowsay je dirais 2.
                                  edit : je propose qu'on discute des difficultés sur le méta...
                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    4 juillet 2011 à 12:15:55

                                    Equinoxe : Ajouté les difficultés pour Cowsay, Xor, César et Vigénère.
                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      4 juillet 2011 à 12:17:40

                                      il faudrait aussi finir les solutions.
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        4 juillet 2011 à 12:57:34

                                        Les notes sont sur 4 ou sur 5? Parce que pour l'exerciceCrypto 2 : Le chiffre de Vigénère On dirait que c'est la difficulté max...
                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          4 juillet 2011 à 13:04:22

                                          C'est vrai qu'il faudrait une icone de "pas de difficulté". Je m'en charge de suite (mettre en gris l'icône suffira sûrement).
                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            4 juillet 2011 à 13:09:12

                                            Franchement, pour cowsay, j'aurais mis plus de 2 (3 peut-être) car normalement, à ce que j'avais compris, on doit aussi gérer les différents paramètre du main.

                                            Et pour Vigenère, j''aurais mis 3 aussi. Il me semble plutôt simple non ? C'est seulement le 3em Niveau qui mérite 4.
                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                            🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.
                                              4 juillet 2011 à 13:10:51

                                              Equinoxe : Corrigé les niveaux de difficulté.
                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                4 juillet 2011 à 13:16:26

                                                Ah, zut, je n'avais pas vu ton message, @che. Mon message signifiait "J'ai ajouté les images de non-difficulté". D'ailleurs, elles sont bien comme ça ?

                                                Pour cowsay, les paramètres du main ne sont pas vraiment importants : il suffit de récupérer le premier. C'est fait en deux lignes (check de argc et récupération de argv[1]). Si on veut améliorer, on peut concaténer tous les arguments avec un espace entre chaque.

                                                Et vigénère mérite plus que césar, puisque son niveau 1 & 2 sont globalement aussi durs que césar, et que son niveau 3 est plus dur.

                                                Pour moi, mettre cowsay et vigénère ensemble serait une hérésie. ^^ (D'ailleurs, j'entame la correction du triangle de pascal, plutôt facile à faire pour une première correction).
                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  4 juillet 2011 à 13:34:15

                                                  peut être que tu devrait mettre la petite flamme en gris ou en couleur normale et faire un truc du genre :
                                                  IIIIIIIIII
                                                  en remplacant le jaune par les flammes colorés et le rouge par les flames en niveau de gris.

                                                  EDIT : dsl j'avait pas vu :p

                                                  par contre on devrait plutôt noter sur 10 pasque la la dificulté max est atteinte rapidement ...
                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    4 juillet 2011 à 13:35:09

                                                    C'est pas déjà ce qu'il fait ?
                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                    🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.
                                                      4 juillet 2011 à 13:37:32

                                                      A oui peut-être pas 10 mais sur 6 ou 7 voir 8 car c'est vrais que la difficulté est atteinte plutôt rapidement.
                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                      🍊 - Étudiant - Codeur en C | Zeste de Savoir apprenez avec une communauté | Articles  - ♡ Copying is an act of love.
                                                        4 juillet 2011 à 13:39:49

                                                        Disons qu'à mon avis le chiffre de Vigénère mérite bien ses quatre sur cinq.

                                                        Mais il serait en effet possible de mettre des demis, pour avoir au final une note ayant dix possibilités, sans avoir à élargir les tableaux (qui risqueraient de ne plus rentrer dans les plus petites résolutions).

                                                        Je propose que la suite de la discussion se fasse là-bas.
                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          4 juillet 2011 à 13:52:46

                                                          germino : ajout de la partie "je veux proposer une solution" et la partie "Qui se cache derrière Exercice Cpp"
                                                          • Partager sur Facebook
                                                          • Partager sur Twitter

                                                          [Exercices] Venez vous entraîner !

                                                          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                          • Editeur
                                                          • Markdown