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

 Delphi Discussion :

Comment trouver toutes les combinaisons possibles ?


Sujet :

Delphi

  1. #1
    Membre averti
    Homme Profil pro
    Paramétreur de progiciels
    Inscrit en
    Octobre 2006
    Messages
    970
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Paramétreur de progiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 970
    Points : 381
    Points
    381
    Par défaut Comment trouver toutes les combinaisons possibles ?
    Bonjour,

    Je cherche à lister toutes les combinaisons possibles pour une chaine de 4 caractères fabriquée à partir de la table de caractères suivante : 'abc'.

    Je ne sais pas trop comment développer mon algorithme, j'imagine que je dois utiliser la récursivité ?

    Je voudrais pourvoir par la suite pouvoir avec cette même fonction générer toutes les combinaisons possibles pour une chaine de 5 caractères avec 'abcd'.

    Comment feriez-vous ?

    Pouvez-vous me donner des pistes ?

    Merci,
    ZiP

  2. #2
    Expert éminent
    Avatar de qi130
    Homme Profil pro
    Expert Processus IT
    Inscrit en
    Mars 2003
    Messages
    3 901
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 63
    Localisation : France

    Informations professionnelles :
    Activité : Expert Processus IT
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2003
    Messages : 3 901
    Points : 6 026
    Points
    6 026
    Par défaut
    Une idée à 4 sous (pas + vue l'heure).

    Ca revient à "compter" de 0000 à 2222 en substituant 0 à A, 1 à B et 2 à C et tout ceci en base 3:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    0000 pour AAAA
    0001 pour AAAB
    0002
    0010
    0011
    0012
    ...
    etc
    "Il n'y a pas de bonnes réponses à une mauvaise question." (M. Godet)
    -----------------------
    Pensez à cloturer votre sujet - Aucune réponse aux sollicitations techniques par MP
    Usus magister est optimus

  3. #3
    Membre confirmé
    Homme Profil pro
    Santé
    Inscrit en
    Septembre 2010
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Santé
    Secteur : Santé

    Informations forums :
    Inscription : Septembre 2010
    Messages : 290
    Points : 534
    Points
    534
    Par défaut
    Salut,

    En programmation la récursivité est à bannir !
    C'est la démarche du sous-préfet : distinguée, mais lourde et sans grand pouvoir.
    Laissons cela au raisonnement mathématique et aux mathématiciens qui savent s'en servir à propos.

    Si j'ai bien compris, tu veux placer n objets discernables dans k emplacements en tenant compte de l'ordre (aaab <> abaa).
    En analyse combinatoire, on appelle ça un arrangement avec répétition.
    Tu auras donc n^k arrangements possibles :
    3^4 = 81 dans le 1er cas.
    4^5 = 1024 dans le 2ème.

    Je te donne un exemple pour le 1er cas (fait sous D7).
    Je te laisse le soin d'en faire une routine plus générale et plus optimisée. (Bein ouais, quand même )
    J'ai choisi une StringList pour le sort et le SaveToFile (bien que la liste soit 'naturellement' triée dans cet exemple) :


    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
    var TempList    : TStrings;
        C1,C2,C3,C4 : Char;
        i           : Integer;
    begin
    TempList := TStringList.Create;
    try
      for C1 := 'a' to 'c' do begin
        for C2 := 'a' to 'c' do begin
          for C3 := 'a' to 'c' do begin
            for C4 := 'a' to 'c' do begin
              TempList.Add(C1+C2+C3+C4);
            end;
          end;
        end;
      end;
      for i := 0 to TempList.Count-1 do Memo1.Lines.Add(TempList[i])
    finally TempList.Free;   end;

    PS: J'aime beaucoup l'approche de qi130.
    Mais je ne vois pas le moyen de l'exploiter efficacement. Dommage.

  4. #4
    Membre averti
    Homme Profil pro
    Paramétreur de progiciels
    Inscrit en
    Octobre 2006
    Messages
    970
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Paramétreur de progiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 970
    Points : 381
    Points
    381
    Par défaut
    Bonjour,

    J'avais déjà pensé à ça mais le problème qui se pose, c'est que le nombre de caractères peut varier.

    Par conséquent, le notre de boucles for va varier aussi.

    Imaginons avec 25 caractères...

    C'est pour ça que j'étais parti sur du récursif

    L'ordre n'est pas nécessaire dans mon cas, mais juste avoir toutes les possibilités.

    Je vais étudier ta proposition,
    Merci,
    ZiP

  5. #5
    Membre éclairé Avatar de DOLPat®
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    Février 2003
    Messages
    426
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : Février 2003
    Messages : 426
    Points : 790
    Points
    790
    Par défaut
    bonjour

    Tu peux essayer avec ça: (vu ici; Merci à Paul )

    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
    const
      LongMaxi = 4;
     
    procedure Combine(s:string);
    var
      c: char;
    begin
      if length(s) = LongMaxi+1 then exit;
        Form2.Memo1.Lines.Add(s);
      for c := 'a' to 'c' do
        Combine(s + c);
    end;
     
    procedure TForm2.FormCreate(Sender: TObject);
    var
      i:    Integer;
      c:    Char;
    begin
      for c := 'a' to 'c' do
        combine(c);
    end;
    Mais si tu comptes partir sur une base de de recherche sur 25 caractères, à mon avis, va falloir être patient ou alors écrire le code en assembleur...

    Pat.
    À +
    Pat.


    Si vous avez trouvé chaussure à votre pied... euh solution à votre problème, n'oubliez pas de clôturer le sujet en le marquant comme:
    ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
    Windows 8.1, Lazarus 1.8.2 SVN 57369 FPC 3.0.4 x86_64-win64-win32/win64

  6. #6
    Membre confirmé
    Homme Profil pro
    Santé
    Inscrit en
    Septembre 2010
    Messages
    290
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Santé
    Secteur : Santé

    Informations forums :
    Inscription : Septembre 2010
    Messages : 290
    Points : 534
    Points
    534
    Par défaut
    Citation Envoyé par [ZiP] Voir le message
    Imaginons avec 25 caractères...

    Là, ça devient de la bistromatique.
    Il faudrait peut-être revoir la logique de ton application. Car, de fait, on a rarement besoin de devoir lister tous les arrangements possibles. Les parcourir sera dejà assez gourmand en temps !

    Es-tu sûr de devoir lister le résultat ?

  7. #7
    Membre chevronné

    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    935
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2009
    Messages : 935
    Points : 1 765
    Points
    1 765
    Par défaut
    Citation Envoyé par DOLPat® Voir le message
    bonjour

    Tu peux essayer avec ça: (vu ici; Merci à Paul )
    Une petite réécriture :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    procedure Combine(s:string; N : integer);
    var
      C: char;
    begin
      if N>0 then
      begin
        for C := 'a' to 'c' do
          Combine(s+C,N-1);
      end;
      else
        Writeln(S);
    end;
    Pour l'appeler : Pour afficher toutes les combinaisons de 4 caracteres de A à Z, ca prends environ 25 secondes sur mon PC (i5 @ 2.27 GHz) ...

    Mais je rejoins l'avis de Caribensila ... C'est seulement pour un test ? Ou tu as une appli qui nécessite ca ?

  8. #8
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    271
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Italie

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 271
    Points : 491
    Points
    491
    Par défaut
    En reprenant l'idée de qi130, on peut avoir une fonction générale non recursive pour n'importe quelle chaine s de longueur n a combiner sur k positions
    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
    procedure Combine(s : string; k : integer);
    var tab :array[0..100] of integer;
        n,i,j : integer;
    begin
    n:=length(s);
    for i:=0 to k do tab[i]:=0;
    while tab[k]=0 do
      begin
      for i:=k-1 downto 0 do write(s[tab[i]+1]);
      writeln;
      tab[0]:=(tab[0]+1) mod n;
      j:=0;
      while tab[j]= 0 do
        begin
        inc(j);
        tab[j]:=(tab[j]+1) mod n;
        end;
      end;
    end;
    L'appel se fait par
    ou bien
    Si on veux se passer de la fonction mod, on remplace la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
      tab[0]:=(tab[0]+1) mod n;
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    inc(tab[0]); 
    if tab[0]=n then tab[0]=0;
    meme traitement pour la ligne 16
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    inc(tab[j]); 
    if tab[j]=n then tab[j]=0;

  9. #9
    Membre averti
    Homme Profil pro
    Paramétreur de progiciels
    Inscrit en
    Octobre 2006
    Messages
    970
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Paramétreur de progiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 970
    Points : 381
    Points
    381
    Par défaut
    Bonjour fab256,

    Je viens de tester ton code, c'est exactement ce que je voulais !

    Je l'ai modifié ainsi pour le tester :
    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
    procedure Combine(s: String; k: Integer);
    var
         tab : array [0..100] of Integer;
         n,i,j : Integer;
         chaine : String;
    begin
         n := Length(s);
     
         for i:=0 to k do
              tab[i] := 0;
     
         while tab[k]=0 do
         begin
              chaine := '';
     
              for i:=k-1 downto 0 do
                   chaine := chaine + s[tab[i] + 1];
     
              Form1.ListBox1.Items.Add(chaine);
              tab[0] := (tab[0] + 1) mod n;
              j := 0;
     
              while tab[j]= 0 do
              begin
                   Inc(j);
                   tab[j] := (tab[j] + 1) mod n;
              end;
         end;
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    begin
         Combine('abc', 3);
         Label1.Caption := IntToStr(ListBox1.Count);
    end;
    Merci !
    ZiP

  10. #10
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 447
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    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 447
    Points : 24 849
    Points
    24 849
    Par défaut
    Un gros sujet de 5 Pages "Test possibilités possible longue boucle" a déjà apporter de nombreuses réponses sur la combinatoire !
    A Lire !
    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

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 06/01/2015, 15h41
  2. Trouver toutes les combinaisons possibles
    Par Onimaru dans le forum Algorithmes et structures de données
    Réponses: 3
    Dernier message: 27/11/2013, 15h35
  3. [XL-2010] Trouver toutes les combinaisons possibles de plusieurs mots
    Par Faneos dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 15/12/2012, 19h17
  4. Trouver toutes les combinaisons possibles de plusieurs tableaux
    Par divayht dans le forum Algorithmes et structures de données
    Réponses: 4
    Dernier message: 23/08/2010, 20h56
  5. toutes les combinaisons possibles
    Par marocleverness dans le forum Algorithmes et structures de données
    Réponses: 6
    Dernier message: 29/05/2006, 00h11

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