afficher les combinaisons de chaine de caractères

afficher les combinaisons de chaine de caractères - C - Programmation

Marsh Posté le 29-11-2009 à 16:52:48    

Je voulais afficher toutes les combinaisons possibles de taille 2, de taille 3 jusqu'à taille N.
par exemple on a 4 mots(chaine de caractère):
 

Citation :

un
deux
trois
quatre


 
les combinaisons possibles sont :

Citation :


un deux
un trois
un quatre
deux trois
deux quatre
trois quatre
un deux trois
un deux quatre
un trois quatre
deux trois quatre
un deux trois quatre
 


 
Donc on a N = 4 et le nombre de combinaisons = 11
On ne s'intéresse pas au combinaison formant par 1 seul mot(un, deux,trois et quatre).
 
Voici une solution:

Code :
  1. #include <stdio.h>
  2. #define N 5
  3. void afficher(int etat[], char *t[])
  4. {
  5.   int i;
  6.   for (i = 0; i < N; i++)
  7.     if (etat[i])
  8.       printf("%s ", t[i]);
  9.   puts("" );
  10. }
  11. void partie(int h, int etat[], char *t[])
  12. {
  13.   enum { ABSENT, PRESENT };
  14.   if (h < 0)
  15.     afficher(etat, t);
  16.   else
  17.     {
  18.       etat[h] = ABSENT;
  19.       partie(h - 1, etat, t);
  20.       etat[h] = PRESENT;
  21.       partie(h - 1, etat, t);
  22.     }
  23. }
  24. int main(void)
  25. {
  26.   char *t[N] = { "nom", "prenom", "age", "adresse", "emploi" };
  27.   int etat[N];
  28.   partie(N - 1, etat, t);
  29.   return 0;
  30. }


 
il affiche :

Citation :

nom
prenom
nom prenom
age
nom age
prenom age
nom prenom age
adresse
nom adresse
prenom adresse
nom prenom adresse
age adresse
nom age adresse
prenom age adresse
nom prenom age adresse
emploi
nom emploi
prenom emploi
nom prenom emploi
age emploi
nom age emploi
prenom age emploi
nom prenom age emploi
adresse emploi
nom adresse emploi
prenom adresse emploi
nom prenom adresse emploi
age adresse emploi
nom age adresse emploi
prenom age adresse emploi
nom prenom age adresse emploi


 
Comment modifier cette solution pour obtenir les combinaisons à partir de taille 2 et soit aussi triée (taille 2 puis 3 puis 4 puis 5) ?
 
Le résultat souhaité obtenu est :

Citation :


 
nom prenom
nom age
nom adresse
nom emploi
prenom age
prenom adresse
prenom emploi
age adresse
age emploi
adresse emploi
nom prenom age
nom prenom adresse
nom prenom emploi
nom age adresse
nom age emploi
nom adresse emploi  
prenom age adresse
prenom age emploi
prenom adresse emploi
age adresse emploi
nom prenom age adresse
nom prenom age emploi
nom prenom adresse emploi
nom age adresse emploi
prenom age adresse emploi
nom prenom age adresse emploi


 
Pouvez vous m'aidez ?
 
Merci.


Message édité par msedirim le 29-11-2009 à 16:53:44
Reply

Marsh Posté le 29-11-2009 à 16:52:48   

Reply

Marsh Posté le 29-11-2009 à 19:04:39    

Salut
 
J'ai trouvé une solution qui permet cela, qui se base aussi sur un tableau d'état. Seulement j'ai fait une fonction  
 
void afficheToutesPossibilites (char* t[N], unsigned nbAff)
 
que j'appelle dans le main

Code :
  1. for (i=2;i<=N;i++)
  2.        afficheToutesPossibilites(t,i);


 
Cette fonction affiche toutes les possibilité de combinaisons à nbAff mots. Du coup l'affichage est trié.
 
Elle met l'état du premier mot à 1 puis appelle une fonction récursive qui se charge de faire toutes les possibilités avec les mots qui restent. Puis elle passe au 2eme mot et ainsi de suite.
 
Je ne sais pas si je suis très clair, mais j'espère t'avoir au moins donné une piste.


---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 30-11-2009 à 07:58:07    

Bonjour,
 
S'il vous plait, pouvez vous me détailler encore votre solution car je n'ai pas compris ? C'est possible de mettre la solution pour comprendre mieux car j'ai en besoin après dans le reste de mon travail ?
 
 
Merci.

Reply

Marsh Posté le 30-11-2009 à 12:53:29    

Non je ne mettrai pas la solution car ce n'est pas la coutume ici.
 
 
J'ai vu ton autre post sur le tri donc je suppose que tu stockes tes résultats et que tu veux les trier. C'est une solution, surtout si tu dois réutiliser plus tard tes résultats. Ma solution se contente d'afficher bien que si tu le veux tu peux toujours stocker au lieu d'afficher. Mais dans ce cas, peut-être qu'un tri est plus efficace, je n'ai pas comparé.  
 
En tout cas voici le fonctionnement de ma solution lorsqu'elle affiche les solutions à 3 mots (sur 4)
 

Citation :

nom prenom age adresse
  0         0       0       0
 
début fonction récursive nbAff=3
        nom prenom age adresse
         1         0       0       0
 
        début fonction récursive nbAff=2
                nom prenom age adresse
                 1         1       0      0
 
                début fonction récursive nbAff=1
                        nom prenom age adresse
                         1         1        1       0
 
                        début fonction récursive nbAff=0
                                affichage
                        fin
 
                        nom prenom age adresse
                         1         1       0       0
 
                        nom prenom age adresse
                         1         1        0       1
 
                        début fonction récursive nbAff=0
                                affichage
                        fin
 
                        nom prenom age adresse
                         1         1       0       0
 
                        plus possible d'avancer
                fin
 
                nom prenom age adresse
                 1        0        0        0
 
                nom prenom age adresse
                 1         0       1        0
 
                début fonction récursive nbAff=1
                        nom prenom age adresse
                         1         0       1       1
 
                        début fonction récursive nbAff=0
                                affichage
                        fin
 
                        nom prenom age adresse
                         1         0       1      0
 
                        plus possible d'avancer
                fin
 
                nom prenom age adresse
                 1         0       0       0
 
                plus possible d'avancer
        fin
 
        nom prenom age adresse
         0         0       0      0
 
        nom prenom age adresse
         0         1       0       0
 
        début fonction récursive nbAff=2
                nom prenom age adresse
                 0         1       1       0
...
 


 
Tu dois rendre ça pour quand?


Message édité par ptitchep le 30-11-2009 à 12:58:29

---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 01-12-2009 à 00:34:08    

Le mercredi matin.
 
Le temps passe mais je n'arrive pas à résoudre le problème.
 
 
 

Reply

Marsh Posté le 01-12-2009 à 00:42:24    

Le mercredi matin.
 
Le temps passe mais je n'arrive pas à résoudre le problème.
 
 
 

Reply

Marsh Posté le 01-12-2009 à 00:49:45    

Salut,
 
si j'étais toi, j'utiliserai la méthode des masques binaires pour valider/inhiber une valeur et acceder aux suivantes.
Un simple tableau peut ensuite te restituer les noms des valeurs qui correspondent.
 
Par exemple: pseudo code C:
 
enum
{    nom              1<<0;
     prenom         1<<1;
     adresse        1<<2;
}  
 
tu peux ensuite utiliser les opérateurs bits à bits pour exprimer tous les résultats.
Si tu as de la doc sur le C: | ; & ; ^ et ~    .
 
J'ai pas trop le temps d'expliquer plus, si tu te sent à l'aise avec ces opérateurs, je pense que ca peux aller assez vite.
 
N'hésitez pas a me filer un coup de main sur mon topic si vous avez le temps... : )
 
Ciao!

Reply

Marsh Posté le 01-12-2009 à 02:45:28    

Hum c'est une idée qu'il faudrait creuser, même si rien ne me vient à l'esprit comme ça, il y a sans doute moyen de faire quelque chose.
Le problème c'est si N = 256815. Tu n'auras jamais assez de bits. La solution de msedirim ainsi que la mienne fonctionnent, même s'il faudrait sans doute créer dynamiquement les tableaux plutôt que de rentrer N mots à la main à la déclaration.
Bon OK, la civilisation humaine disparaîtra avant que toutes les possibilités ne soient affichées mais là n'est pas la question....


---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 01-12-2009 à 09:40:33    

Bonjour,
Si on 4 mots:

Citation :


un
deux
trois
quatre


 
alors le résultat souhaité obtenu est :

Citation :

un deux
un trois
un quatre
deux trois
deux quatre
trois quatre
un deux trois
un deux quatre
un trois quatre
deux trois quatre
un deux trois quatre

Citation :


 
Cette fonction affiche toutes les possibilité de combinaisons à nbAff mots. Du coup l'affichage est trié.


 
Est ce que votre solution donne le résultat cité au dessus ?
 
car je n'ai pas compris :
Citation

Citation :

void afficheToutesPossibilites (char* t[N], unsigned nbAff)


 
-Qu'est ce que contient 'tab': les 4 mots ou bien le résultat ?
-nbAff présente quoi dans cet exemple ?
 
J'ai posé ma solution alors pouvez vous me poser votre solution pour comprendre mieux ?
 
Je voulais stocker le résultat dans un tableau pour l'utiliser après donc ce tableau qui sera allouer dynamiquement mais le problème est combien on doit réserver des cases pour ce tableau car le résultat ne contient pas toutes les combinaisons sauf de taille 2 jusqu'à taille N?
Si on N=4 alors le nombre de toutes les combinaisons sont :

Code :
  1. int nombre;
  2. nombre=pow(2,N);


 
Mais en réalité la taille de tableau est inférieur que 'nombre' alors pour la libération après de ce tableau est ce que je fais jusqu'à la taille 'nombre' ou bien jusqu'à le nombre des cases réellement remplies?
 
Est ce que on peut déterminer par une formule ou autre ? :
- les combinaisons de taille 2: ici on a 6 si N=4
- les combinaisons de taille 3: ici on a 4 si N=4
- les combinaisons de taille 4: ici on a 1 si N=4
 
Merci.

Message cité 1 fois
Message édité par msedirim le 01-12-2009 à 09:52:13
Reply

Marsh Posté le 01-12-2009 à 10:17:51    

msedirim a écrit :


Est ce que votre solution donne le résultat cité au dessus ?

Oui

msedirim a écrit :


car je n'ai pas compris :
Citation

Citation :

void afficheToutesPossibilites (char* t[N], unsigned nbAff)


 
-Qu'est ce que contient 'tab': les 4 mots ou bien le résultat ?
-nbAff présente quoi dans cet exemple ?


Tab contient 0 ou 1, ABSENT ou PRESENT c'est juste que je n'ai pas fait d'enum.
nbAff contient le nombre de mots à afficher restant. Au premier appel il vaut 2 (on commence avec les combinaisons à 2 mots) puis 3, puis 4, ..., puis N.
En fait ma fonction afficheToutesPossibilites est inutile, c'était juste pour montrer qu'une boucle sur une fonction avec les bons arguments permettait d'afficher les résultats dans l'ordre. Elle se contente d'initialiser etat avec des 0 partout et d'appeler la fonction récursive qui elle fait le boulot. Elle recoit le tableau d'état, le tableau de mot, le nombre de mots restant à afficher et la position de départ dans le tableau. Par exemple au début tout est à 0, elle va recevoir nbAff=2 (on commence par les solutions à 2 mots) et debut=0. elle va cocher etat[debut] puis se rappeler avec nbAff=1 (il ne reste qu'un mot à cocher) et debut = 1 (on a deja coché le mot 0). Elle va alors cocher etat[debut] puis se rappeler avec nbAff=0 (et debut = 0). nbAff=0 donc plus rien à cocher, on affiche et on retourne. On efface etat à partir de début, puis on avance (debut++), on coche etat[debut] puis on se réappelle avec debut+1 et nbAff-1, etc
 

msedirim a écrit :


J'ai posé ma solution alors pouvez vous me poser votre solution pour comprendre mieux ?

Recopier ma solution ne fera pas comprendre mieux au contraire. Et puis la note n'est pas pour moi.
 

msedirim a écrit :


Je voulais stocker le résultat dans un tableau pour l'utiliser après donc ce tableau qui sera allouer dynamiquement mais le problème est combien on doit réserver des cases pour ce tableau car le résultat ne contient pas toutes les combinaisons sauf de taille 2 jusqu'à taille N?
Si on N=4 alors le nombre de toutes les combinaisons sont :

Code :
  1. int nombre;
  2. nombre=pow(2,N);


 
Mais en réalité la taille de tableau est inférieur que 'nombre' alors pour la libération après de ce tableau est ce que je fais jusqu'à la taille 'nombre' ou bien jusqu'à le nombre des cases réellement remplies?
 
Est ce que on peut déterminer par une formule ou autre ? :
- les combinaisons de taille 2: ici on a 6 si N=4
- les combinaisons de taille 3: ici on a 4 si N=4
- les combinaisons de taille 4: ici on a 1 si N=4
 
Merci.


Oui on doit pouvoir par une formule . Sans réfléchir je dirais que nombre < pow(2,N) parce que pour toi "un, deux" c'est la même chose que "deux, un". Mais je peux me tromper. Je n'ai pas le temps ce matin de chercher plus, je reviendrai si j'ai le temps cet aprem.


---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 01-12-2009 à 10:17:51   

Reply

Marsh Posté le 01-12-2009 à 23:58:30    

Tu me fais tellement pitié à poster sur tous les forums ...
T'as juste à modifier quelques trucs dans le code à Candide ...
 :pt1cable:  :pt1cable:  :pt1cable:  :pt1cable:  :pt1cable:  :pt1cable:  :pt1cable:  
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define N 5
  4. void affiche(int *tab, int c) {
  5. int i;
  6. if (c < 2)
  7.  return;
  8. for (i = 0; i < N; i++) {
  9.  if (tab[i]) {
  10.   printf("%d ", tab[i]);
  11.  }
  12. }
  13. puts("" );
  14. }
  15. void parmis(int *tab, int h, int c) {
  16. enum { ABSENT, PRESENT };
  17. if (h < 0) {
  18.  affiche(tab, c);
  19. }
  20. else {
  21.  tab[h] = PRESENT;
  22.  c++;
  23.  parmis(tab, h-1, c);
  24.  tab[h] = ABSENT;
  25.  c--;
  26.  parmis(tab, h-1, c);
  27. }
  28. }
  29. int main(void) {
  30. int tab[N] = { 0 };
  31. parmis(tab, N-1, 0);
  32. return EXIT_SUCCESS;
  33. }


Reply

Marsh Posté le 02-12-2009 à 08:03:42    

Je me suis fait grillé, je pensais lui mettre ce matin au dernier moment pour la même raison :lol:  

Code :
  1. void trouveSuite (char* t[N], unsigned nbAff, int etat[N], int debut)
  2. {
  3.         if (nbAff == 0)
  4.         {
  5.                 afficher(etat,t);
  6.                 return;
  7.         }
  8.         for (; debut<=N - nbAff;debut++)
  9.         {
  10.                 etat[debut] = 1;
  11.                 trouveSuite (t, nbAff - 1, etat, debut+1);
  12.                 memset (etat + debut, 0, sizeof(int) * (N - debut));
  13.         }
  14. }
  15. int main(void)
  16. {
  17.         char *t[N] = { "un", "deux", "trois", "quatre" };
  18.         int etat[N];
  19.         int i;
  20.         memset (etat, 0, sizeof(int) * N);
  21.         for (i=2;i<=N;i++)
  22.                 trouveSuite(t, i, etat, 0);
  23.         return 0;
  24. }


---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 02-12-2009 à 08:54:05    

Citation :

Tu me fais tellement pitié à poster sur tous les forums ...
T'as juste à modifier quelques trucs dans le code à Candide ...


 
Merci.Mais votre solution affiche des  suite de 1 pas de mots . elle m'affiche:
1111
111
11
...
....
 

Citation :

Je me suis fait grillé, je pensais lui mettre ce matin au dernier moment pour la même raison


 
Merci. Mais, j'ai ajouté à votre solution:

Code :
  1. #define N 4
  2. void afficher(int etat[], char *t[])
  3. {
  4.   int i;
  5.   for (i = 0; i < N; i++)
  6.     if (etat[i])
  7.       printf("%s ", t[i]);
  8.   puts("" );
  9. }


 
Je voulais stocker le résultat dans un tableau pour l'utiliser après dans la suite dans mon programme principal donc ce tableau qui sera allouer dynamiquement mais le problème est combien on doit réserver des cases pour ce tableau car le résultat ne contient pas toutes les combinaisons sauf de taille 2 jusqu'à taille N?
Si on N=4 alors le nombre de toutes les combinaisons sont :

Code :
  1. int nombre;
  2. nombre=pow(2,N);


 
 
Mais en réalité la taille de tableau est inférieur que 'nombre' alors pour la libération après de ce tableau est ce que je fais jusqu'à la taille 'nombre' ou bien jusqu'à le nombre des cases réellement remplies?
 
Est ce que on peut déterminer par une formule ou autre ? :
- les combinaisons de taille 2: ici on a 6 si N=4
- les combinaisons de taille 3: ici on a 4 si N=4
- les combinaisons de taille 4: ici on a 1 si N=4
 
 
 
Quelles sont les modifications à faire pour que cette solution m'affiche le résultat dans un tableau qu'on puisse l'utiliser après ? Est ce que c'est mieux de faire ce tableau dans cette solution qui va nous retourner ce tableau ou bien considérer votre solution comme une fonction dans mon programme principal et on passe à cette fonction le tableau de résultat ?
 
Merci.
 

Message cité 1 fois
Message édité par msedirim le 02-12-2009 à 09:05:04
Reply

Marsh Posté le 02-12-2009 à 16:31:16    

msedirim a écrit :

Merci.Mais votre solution affiche des  suite de 1 pas de mots .


Evidemment il faut réfléchir encore un peu (ce que tu ne fais pas ...)  :pfff:  :pfff:  :pfff:

Reply

Marsh Posté le 02-12-2009 à 16:41:56    

Pouet_forever a écrit :


Evidemment il faut réfléchir encore un peu (ce que tu ne fais pas ...)  :pfff:  :pfff:  :pfff:


Inutile, nous sommes là pour ça :pfff:


---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 02-12-2009 à 20:23:01    

pour déterminer le 'nombre' de toutes les combinaisons de taille N alors on 2 à la puissance N moins -1.
Voici le code:

Code :
  1. int nombre;
  2. nombre=pow(2,N) - 1;


 
 
 
par exemple penons p=2 alors Le nombre de combinaisons de taille p est:
 
N!/p!/(N-p)!
 
Quelle est l'équivalent de cette formule en C ?
 
pas de fonctions prédéfinies en C ?
 
Merci.


Message édité par msedirim le 02-12-2009 à 20:24:07
Reply

Marsh Posté le 02-12-2009 à 20:44:03    

Voici mon essai:
 

Code :
  1. int Fact(int nombre)
  2. {
  3.     int resultat = nombre;
  4.     int i;
  5.     for (i=2, i<nombre ; i++)
  6.         resultat *= i;
  7.    
  8.     return resultat;
  9. }


 
Que proposez vous ?


Message édité par msedirim le 02-12-2009 à 20:44:52
Reply

Marsh Posté le 02-12-2009 à 21:47:44    

Moi j'aurais pensé récursivité pour une factorielle.
Ca m'étonne qu'il n'y ait pas ça dans math.h ou quelque chose du genre.


---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 03-12-2009 à 07:50:15    

Code :
  1. memset (etat, 0, sizeof(int) * N);


 
- Pouvez vous m'expliquer encore cette fonction et pourquoi vous l'utiliser?
 
- Est ce que dans la solution on ne fait aucune libération d'espace alloué ?
 
-

Code :
  1. nombre=pow(2,N) - 1;


Mais en réalité la taille de tableau qui va contenir le résultat est inférieur que 'nombre' alors pour la libération après de ce tableau est ce que on fait jusqu'à la taille 'nombre' ou bien jusqu'à le nombre des cases réellement remplies?
 
-Quelles sont les modifications à faire pour que cette solution m'affiche le résultat dans un tableau qu'on puisse l'utiliser après ? Est ce que c'est mieux de faire ce tableau dans cette solution qui va nous retourner ce tableau ou bien considérer votre solution comme une fonction dans mon programme principal et on passe à cette fonction le tableau de résultat ?
 
Merci.
 


Message édité par msedirim le 03-12-2009 à 09:04:11
Reply

Marsh Posté le 03-12-2009 à 15:00:03    

man memset
 
Il n'y a aucune allocation (dynamique) de mémoire donc aucune libération.
 
On libère ce que l'on a alloué mais en principe on n'alloue que ce dont on a besoin.
 
A voir selon le besoin les deux sont possibles.


---------------
deluser --remove-home ptitchep
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed