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++Builder Discussion :

Plusieurs tirages de couples sans doublons


Sujet :

C++Builder

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    573
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 573
    Points : 713
    Points
    713
    Par défaut Plusieurs tirages de couples sans doublons
    Salut

    J ai une liste d"équipes .
    Chaque équipe va disputer 5 matchs sans rencontrer 2 fois le même adversaire .

    Résoudre ce probléme n est pas si compliqué , pourtant dans certains cas et surtout lorsque la liste d'équipes est petite , un mauvais tirage surgit , il me reste un doublon qui se sont déjà rencontrés .

    Je pourrais ne pas valider le tirage et le recommencer , mais je pense que vous connaissez les caprices du random .

    N'y aurait-il pas une astuce ?

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 459
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 459
    Points : 24 873
    Points
    24 873
    Par défaut
    Utilise RandomFrom comme dans ma fonction RandomFromExclude dans le random non répétitif
    Elle retire du tableau les valeurs déjà tirés et le renvoi comme résultat

    Une autre approche est de mémoriser les valeurs déjà tirées, je ne retrouve pas le sujet où l'on avait évoqué, idem une fonction Delphi prête à l'emploi

    Sinon, c'est juste un problème de combinatoire, tu veux une "Permutation sans répétition", il y a plein de sujet Delphi qui traite de cela !
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    573
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 573
    Points : 713
    Points
    713
    Par défaut
    Citation Envoyé par ShaiLeTroll Voir le message
    Utilise RandomFrom
    Une autre approche est de mémoriser les valeurs déjà tirées, je ne retrouve pas le sujet où l'on avait évoqué, idem une fonction Delphi prête à l'emploi
    C est ce que je fais avec randomrange en décrémentant la valeur haute de 2 .
    Mais je ne veux pas obtenir l ensemble des tirages , 60 équipes , çà me donnerait un factoriel 60 , c est beaucoup trop long , en sachant que derrière je dois encore tester la validité de la ligne en prenant en compte 1vs2 et 2vs1

    Si vous avez d autres idées , je suis preneur

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    573
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 573
    Points : 713
    Points
    713
    Par défaut
    1 bouton , 3 memo
    h
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    public:		// Déclarations de l'utilisateur
    void __fastcall TForm1::Tirer(int choix);
    void __fastcall TForm1::Verif();
    cpp
    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
     
    TStringList *Equipes  = new TStringList()  ;
    TStringList *Tirages  = new TStringList()  ;
    TStringList *Test     = new TStringList()  ;
    int TirageOk = 0;
    int nb ;
    int nbEquipes =  12 ;
     
     
    //---------------------------------------------------------------------------
     
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    for ( int i = 1 ; i <=5 ; i++ )
    {
    Memo1->Lines->Add("-------") ;
    TirageOk = 0;
    nb = 0;
    while ( TirageOk < nbEquipes/2   )
               {
               nb++;
               Test->Clear();
               Tirer(2);
               Verif();
               }
     
    Memo3->Lines->Add("good : Tirage "+IntToStr(i)+" Essai "+IntToStr(nb)+" "+IntToStr(TirageOk));
    for ( int i =0 ; i< Test->Count ;i++ )
             {
             Tirages->Add(Test->Strings[i]);
             Memo1->Lines->Add(Test->Strings[i]);
             }
    }
     
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Tirer(int choix)
    {
    for ( int i =1 ; i<=nbEquipes ;i++ )  Equipes->Add(i);
    while ( Equipes->Count > 0 )
               {
               int k =1;
               // si plus de deux equipes , random entre 1 et count sinon reste à 1
               if ( Equipes->Count  >  2 ) {  k = RandomRange(1,Equipes->Count-1); }
     
                     AnsiString temp  = "E_";
                                temp += Equipes->Strings[0];
                                temp += "_vs_E_";
                                temp += Equipes->Strings[k] ;
                     Equipes->Delete(k);
                     Equipes->Delete(0);
                     Test->Add(temp);
                     }
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Verif()
    {
    TirageOk = nbEquipes /2;
     
    for ( int i =0 ; i< Test->Count    ;i++ )
    for ( int j =0 ; j< Tirages->Count ;j++ )
    if  ( Test->Strings[i] == Tirages->Strings[j]  )
          {
          TirageOk-- ;
          Memo2->Lines->Add(TirageOk);
          Memo2->Lines->Add(Test->Strings[i]+"   "+Tirages->Strings[j]);
          }
    }
    //---------------------------------------------------------------------------

  5. #5
    Membre chevronné
    Avatar de Crayon
    Inscrit en
    Avril 2005
    Messages
    1 811
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Avril 2005
    Messages : 1 811
    Points : 2 189
    Points
    2 189
    Par défaut
    Salut cedni, voici un bout de code qui pourrait t'aider.

    D'abord on ajoute les includes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #include <algorithm>    // std::random_shuffle
    #include <vector>       // std::vector
    #include <map>          // std::map
    #include <ctime>        // std::time
    Ensuite tu peux mettre ce bout de code dans un évènement OnClick de bouton:
    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    std::vector<int> EquipeVector;
    for(int i = 1; i <= nbEquipes; ++i)
    {   // On ajoute tous les numéros d'équipe dans un vecteur
        EquipeVector.push_back(i);
    }
     
    std::srand(unsigned(std::time(0))); // Randomize
     
    // Une map qui contient une équipe ainsi que ces cinq adversaires
    std::map< int, std::vector<int> > EquipeAdversaire;
     
    for(int EquipeCourante = 1; EquipeCourante <= nbEquipes; ++EquipeCourante)
    {
        // On mélange le tout
        std::random_shuffle(EquipeVector.begin(), EquipeVector.end());
     
        // On va itérer les équipes pour trouver nos cinq adversaires
        for(std::vector<int>::iterator EquipeVectorIt = EquipeVector.begin();
            EquipeVectorIt != EquipeVector.end(); ++EquipeVectorIt)
        {
            if(EquipeAdversaire[EquipeCourante].size() >=5)
            {   // On a déjà nos 5 adversaires
                EquipeVector.erase(std::find(EquipeVector.begin(), EquipeVector.end(), EquipeCourante));
                break;
            }
     
            const int AdversairePotentiel = *EquipeVectorIt;
     
            if(EquipeCourante == AdversairePotentiel)
            {   // On ne peut pas jouer contre soi-même
                continue;
            }
            if(std::find(EquipeAdversaire[AdversairePotentiel].begin(),
                EquipeAdversaire[AdversairePotentiel].end(), EquipeCourante) !=
                EquipeAdversaire[AdversairePotentiel].end())
            {   // On a déjà jouer contre cet adversaire
                continue;
            }
     
            if(EquipeAdversaire[AdversairePotentiel].size() < 5)
            {   // Notre adversaire potentiel n'a pas cinq parties, on peut donc jouer contre lui
                EquipeAdversaire[EquipeCourante].push_back(AdversairePotentiel);
                EquipeAdversaire[AdversairePotentiel].push_back(EquipeCourante);
            }
        }
    }
     
    // -- Code pour tester débute ici --
    Memo1->Lines->Clear();
    int Count = 0;
    Memo1->Lines->BeginUpdate();
    for(std::map< int, std::vector<int> >::iterator EquipeIt=EquipeAdversaire.begin(); EquipeIt!=EquipeAdversaire.end(); ++EquipeIt)
    {
        for(std::vector<int>::iterator AdversaireIt=EquipeIt->second.begin(); AdversaireIt!=EquipeIt->second.end(); ++AdversaireIt)
        {
             AnsiString temp  = String(++Count) + ": E_";
                        temp += EquipeIt->first;
                        temp += "_vs_E_";
                        temp += *AdversaireIt;
             Memo1->Lines->Add(temp);
        }
        Memo1->Lines->Add("--------------") ;
    }
    Memo1->Lines->EndUpdate();
    if(Count < (nbEquipes * 5))
    {
        MessageDlg(String("Il faut générer encore, il manque des parties à jouer! Il faudrait peut-être appellé la méthode de façon récursive."), mtInformation, TMsgDlgButtons() << mbOK, 0);
    }
    // -- Code pour tester fini ici --
    Il va te falloir un TMemo et définir une valeur à nbEquipes.

    Il est très tard il se pourrait que j'ai fait des conneries
    • Plus un ordinateur possède de RAM, plus vite il peut générer un message d'erreur. - Dave Barry
    • Je n'ai pas peur des ordinateurs. J'ai peur qu'ils viennent à nous manquer. - Isaac Asimov
    • Le code source est comme une belle femme, plus on le regarde, plus on trouve des défauts. - Crayon

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    573
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 573
    Points : 713
    Points
    713
    Par défaut
    merci je garde çà sous le coude même si mon code fonctionne

Discussions similaires

  1. Réponses: 2
    Dernier message: 19/05/2014, 19h13
  2. Tirage aléatoire sans doublon
    Par Cupidon dans le forum SAS STAT
    Réponses: 2
    Dernier message: 13/02/2013, 11h21
  3. Tirage au sort de bannières sans doublon
    Par cedric.c2ware dans le forum WordPress
    Réponses: 0
    Dernier message: 22/04/2011, 18h46
  4. création de table de couples sans doublon
    Par a003147 dans le forum Access
    Réponses: 3
    Dernier message: 30/11/2006, 16h42
  5. Comment mettre à jour une ligne sans doublon via déclencheur
    Par fuelcontact dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 02/08/2004, 15h56

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