IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Combinatoire: combien de nombres a 16 chiffres sans chiffre qui se répete + de 3 fois


Sujet :

C++

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2009
    Messages : 4
    Points : 2
    Points
    2
    Par défaut Combinatoire: combien de nombres a 16 chiffres sans chiffre qui se répete + de 3 fois
    Bonsoir a tous,

    Petit nouveau sur ce forum je viens vous demander votre aide pour un mélange d'algo et de C++.
    Comment ferriez vous pour résoudre le probleme suivant:
    Trouver tous les nombres de 16 chiffres, qui ne commencent pas par 0, et dont aucun chiffre ne se répete plus de 3 fois.

    Je n arrive pas a trouver de méthode "efficace".
    Ma premiere idée, qui marche avec de "petits nombres" était de découper le nombre chiffre par chiffre puis de vérifier les conditions en utilisant un vecteur compteur. Ca marche trés bien jusqu'á 6 ou 7 nombres.
    16 boucles imbriquées pour calculer chiffres par chiffre et vérifier les conditions, ca sera trop lent et donc pas efficace.

    La solution est donc de ne trouver que les "bonnes valeurs" et ensuite de les compter.
    On m'a conseille l'utilisation d'arbre n-aire mais n'ayant jamais utilisé d'arbre j'ai un peu du mal. D'aprés vous cette solution serait elle plus rapide?

    Si vous avez des idées novatrices ou si vous pouvez m'aiguillez concernant la solution par arbre, vous etes les bienvenue

    ps: la solution est bornéé par en dessus et en dessous par 999888777666 5554 et 1000112223334445.

  2. #2
    Membre actif Avatar de Twindruff
    Inscrit en
    Janvier 2005
    Messages
    216
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 216
    Points : 237
    Points
    237
    Par défaut
    Salut jeje87a,
    La solution est donc de ne trouver que les "bonnes valeurs" et ensuite de les compter.
    Oui c'est ça qu'il faut faire, il faut que tu génères tes nombres chiffre par chiffre et donc il faut que tu sache à tout moment à quels chiffres tu as encore droit.
    Tu peux par exemple avoir un tableau de 10 entiers correspondant au nombre de fois que tu peux encore utiliser 0, 1, ..., 9.
    Ensuite tu dois avoir une boucle qui construit tes nombres chiffre par chiffre et s'il te reste des 0 tu peux générer ton nombre actuel avec un zéro à la fin, si tu as des 1 avec un 1 à la fin, et ainsi de suite.

    Et est-ce que tu dois seulement trouver le nombre de nombres qui vérifient ta propriété, ou tous les sortir ?

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2009
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Bonjour

    Merci de ta réponse.
    Je dois juste trouver les nombres vérifiant la propriété mais je pense que le faire en "comptant" toutes les bonnes possibilités c est assez logique.

    Je pense qu il y a une méthode purement mathematiques pour trouver juste le résultat mais pas évident a mon sens.

    J'ai essayé de faire un programme avec un tableau comme tu l as expliqué mais mon programme "vérifie" grace au tableau si le nombre est bon ou non.
    Si tu as une idée de code elle est la bienvenue.

    Merci

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    57
    Détails du profil
    Informations personnelles :
    Âge : 16
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 57
    Points : 65
    Points
    65
    Par défaut
    Tout d'abord, un tableau de 16 char pour représenter ton nombre à 16 chiffres

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char nombre[] = {1,0,0,0,1,1,2,2,2,3,3,3,4,4,4,5}; // le nombre de départ
    Ensuite un tableau de 10 char pour représenter les chiffres utilisés

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char chiffres[] = {3,3,3,3,3,1,0,0,0,0};
    (il y a trois 0, trois 1, ...)

    Ensuite, pour parcourir les solutions, rien de plus simple que d'incrémenter ton nombre!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    //code très naif, ne pas utiliser
    void incrementer(char *nombre, char *chiffres, size_t pos)
    {
        nombre[pos]++; //augmente le chiffre, par exemple de 7 à 8...
    }
    Mais après tu dois vérifier que si ton chiffre passe de 9 à 10, tu le fais passer de 9 à 0, et augmenter celui de la dizaine supérieure:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    //code très naif, ne pas utiliser
    void incrementer(char *nombre, char *chiffres, size_t pos)
    {
        if (++nombre[pos] == 10) //s'il y a une retenue
        {
             nombre[pos] = 0;
             incrementer(nombre, chiffres, pos-1); // on augmente la dizaine supérieure
        }
    }
    Mais après, tu dois vérifier certaines conditions avec chiffres (que nombre[pos] n'ait pas sa case dans chiffres à 3, ...), tu dois tenir à jour un compteur, et une fois que tu auras fini, tu pourras même peut-être trouver des simplifications qui vont augmenter la vitesse de l'algorithme.

    Peut être que ce serait bien de commencer avec moins de chiffres que 16.

    Bonne chance!


  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    19
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 19
    Points : 13
    Points
    13
    Par défaut
    Citation Envoyé par jeje87a Voir le message
    On m'a conseille l'utilisation d'arbre n-aire mais n'ayant jamais utilisé d'arbre j'ai un peu du mal. D'aprés vous cette solution serait elle plus rapide?
    C'est quelqu'un qui sait comment faire qui t'a conseillé ça, ou juste par intuition ?
    Parce que je vois pas en quoi un arbre aiderait à ce problème


    Mon idée à moi serait d'utiliser la récursivité :
    On créé une fonction "creerListeNombresAvecNChiffres(int n, std::vector& aModifier, int& maxChiffres[10])"

    Les paramètres sont :
    - nombre de chiffres dans le nombre
    - une référence vers une liste où stocker le résultat
    - le nombre maximal de chiffres de chaque


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    void creerListeNombresAvecNChiffres(int n, std::vector<int>& aModifier, int& maxChiffres[10]) {
     if (n == 1) {    // fin de la récursivité
      // on veut des nombres à 1 chiffre
      // on retourne donc comme résultat tous les chiffres dont la valeur dans maxChiffres n'est pas à 0
      for (int i = 0; i < 10; i++)
       if (maxChiffres[i] > 0) aModifier.push_back(i);
      return;
     }
     
     // petit opérateur ternaire pour éviter les nombres à 16 chiffres qui commencent par 0
     for (int i = (n == 16 ? 1 : 0); i < 10; i++) {
      if (maxChiffres[i] == 0) continue;  // on ne peut plus rajouter ce chiffre là
      maxChiffres[i]--;    // on fait comme si on l'avait utilisé pour l'appel récursif
     
      // et l'appel récursif
      std::vector<int> resultatsInferieur;
      creerListeNombresAvecNChiffres(n - 1, resultatsInferieur, maxChiffres);
      for (std::vector<int>::iterator j = resultatsInferieur.begin(); j != resultatsInferieur.end(); j++)
       aModifier.push_back(i * 10 * n + *j);
     
      maxChiffres[i]++;
     }
    }
    La récursivité commencerait donc avec :
    creerListeNombresAvecNChiffres(16, resultats, maxChiffresInit);

    Avec "resultats" un std::vector vide où mettre les résultats, et "maxChiffresInit" un tableau de 10 int avec chacun comme valeur 3

    C'est pondu en 5mn chrono donc je garantis pas sans bug, et je ne sais pas si c'est plus rapide ou pas qu'une autre méthode (à voir en détails)

  6. #6
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2009
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    Merci pour vos 2 réponses, je vais les regarder en detail et je vous demanderai plus de conseils ou des precisions par la suite.

    Pour l arbre n-aire, l'idée venait du fait que l'on aurait pu essayer de mettre 10 racines(de 0 a 10) puis chaque branche descendante en fonction de la valeur de l etage precedent.
    Le nombres de feuilles au final donne le nombre de possibilités, le soucis c est que cela donnerai un arbre "immense" et pas tres facile a coder (je n'y suis pas parvenu).

  7. #7
    Membre éclairé

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    717
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Points : 858
    Points
    858
    Par défaut
    Citation Envoyé par jeje87a Voir le message
    ps: la solution est bornéé par en dessus et en dessous par 999888777666 5554 et 1000112223334445.
    Ce qui exclu toute méthode basée sur le comptage une à une des solutions (à moins de posséder un supercalculateur et plusieurs années devant soi).

    Les mathématiques sont donc tes amies.

  8. #8
    Candidat au Club
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2009
    Messages : 4
    Points : 2
    Points
    2
    Par défaut
    J ai trouvé la solution grace au C(n,P) et permutation.

    Resolu

    Merci a vous

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [MySQL] Table "Connectés" : nombre de connexions stoppé au chiffre 127, pourquoi ?
    Par bilou95 dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 06/03/2007, 17h39
  2. Réponses: 4
    Dernier message: 15/06/2006, 17h47
  3. [VB.NET] Textbox -> seulement des chiffres sans API?
    Par Pleymo dans le forum Windows Forms
    Réponses: 10
    Dernier message: 25/04/2005, 14h00
  4. Trouver un maximum entre 2 chiffres sans tests
    Par orichimaru dans le forum Algorithmes et structures de données
    Réponses: 32
    Dernier message: 25/03/2005, 11h05
  5. [LG]Former un nombre entier à partir de chiffre naturel.
    Par lecanardjaune dans le forum Langage
    Réponses: 2
    Dernier message: 12/11/2003, 22h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo