Quand arrive le temps d’un test qui doit utiliser des combinaisons d’une chaîne de caractères / de divers éléments, un programmeur est confronté à faire un algorithme pas toujours évident.
Ci-dessous, deux exemples de code. Le premier permet de trouver toutes les combinaisons d’un nombre de caractères défini parmi ceux d’une chaîne initiale, le second les combinaisons d’éléments divers.
Attention, le terme « combinaison » n’est pas celui décrit en mathématique puisque les résultats ci-dessous montrent que le résultat comprend aussi ceux contenant moins d’éléments que demandés (ex : on demande dans l’exemple 1, 3 caractères, mais des résultats en 1 et 2 caractères sont donnés). Qui peut le plus peut le moins … si ces premiers résultats ne vous sont pas utiles, il suffira de mettre (pour l’exemple 1) : soit SI nTailleItem=3 ALORS tabRes.Ajoute(sItem) soit sChaineDébut = « AAA »
Exemple 1
Cette fonction vient avec quelques paramètres intéressants : chaîne du début (où on commence), chaîne de fin (où on s’arrête) et personnalisation des caractères à utiliser.
Par exemple, avec un nbr de caractères de 3 utilisant la chaîne « ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 », cela donne :
A
B
C
…
9
AA
AB
…
99
AAA
AAB
…
999
tabRésultat est un tableau de chaînes = CombinaisonCaractères(3) fSauveTexte("C:\temp\code.txt",TableauVersChaîne(tabRésultat,RC)) Info("fini")
PROCÉDURE CombinaisonCaractères(LOCAL nNombreCaractèresMax est un entier,sChaineDébut est une chaîne="",LOCAL sChaineFin est une chaîne="",LOCAL sListeCaractères est une chaîne = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") : tableau de chaîne //abcdefghijklmnopqrstuvwxyz" //àèìòùâêîôûäëïöü@ç=+_-()*&?%$/!|\#£¢¤¬¦²³¼½¾{}<>«»°,'.É[]" bTermine est un booléen = Faux //pour terminer le traitement sItem est une chaîne nTailleItem est un entier t est un entier = Taille(sListeCaractères) tabRes est un tableau de chaînes //vérifications d'usage SI sListeCaractères="" ALORS Erreur("La liste des caractères ne peut pas être vide");RENVOYER tabRes SI sChaineDébut>"" _ET_ sChaineFin>"" _ET_ sChaineFin<sChaineDébut ALORS Erreur("La chaîne de fin est inférieure à la chaîne de début");RENVOYER tabRes SI sChaineDébut>"" ALORS SI Taille(sChaineDébut)>nNombreCaractèresMax ALORS Erreur("La taille de la chaîne de début dépasse le nombre de caractères maximum");RENVOYER tabRes //vérifier que les caractères sont dans sListeCaractères POUR c=1 _À_ Taille(sChaineDébut) SI Position(sListeCaractères,sChaineDébut[c])<1 ALORS Erreur(ChaîneConstruit("%1 de la chaîne de début n'est pas contenu dans la liste des caractères",sChaineDébut[c]));RENVOYER tabRes FIN sItem=sChaineDébut;tabRes.Ajoute(sItem) FIN SI sChaineFin>"" ALORS SI Taille(sChaineFin)>nNombreCaractèresMax ALORS Erreur("La taille de la chaîne de fin dépasse le nombre de caractères maximum");RENVOYER tabRes //vérifier que les caractères sont dans sListeCaractères POUR c=1 _À_ Taille(sChaineFin) SI Position(sListeCaractères,sChaineFin[c])<1 ALORS Erreur(ChaîneConstruit("%1 de la chaine de fin n'est pas contenu dans la liste des caractères",sChaineFin[c]));RENVOYER tabRes FIN FIN nTailleItem = Max(Taille(sChaineDébut),1) nDernier est un entier = Position(sListeCaractères,sItem[nTailleItem]) BOUCLE DernierChar(nDernier);nDernier=1 SI bTermine _OU_ sItem=sChaineFin ALORS SORTIR SINON Multitâche(-1) SI AjoutePrécédent(nTailleItem) ALORS sItem[nTailleItem]=sListeCaractères[1];tabRes.Ajoute(sItem) SINON SORTIR FIN RENVOYER tabRes PROCÉDURE INTERNE DernierChar(nDepuisLettre est un entier) POUR c=nDepuisLettre+1 À t sItem[nTailleItem]=sListeCaractères[c] tabRes.Ajoute(sItem) SI bTermine _OU_ sItem=sChaineFin ALORS SORTIR FIN FIN PROCÉDURE INTERNE AjoutePrécédent(LOCAL nPos est un entier) : booléen SI sItem[nPos]=sListeCaractères[t] ALORS SI sItem=Répète(sListeCaractères[t],nTailleItem) ALORS SI nTailleItem<nNombreCaractèresMax ALORS nTailleItem++;sItem=Répète(sListeCaractères[1],nTailleItem) SINON RENVOYER Faux SINON SI PAS AjoutePrécédent(nPos-1) ALORS RENVOYER Faux FIN SINON sItem=Gauche(sItem,nPos-1)+sListeCaractères[Position(sListeCaractères,sItem[nPos])+1]+Répète(sListeCaractères[1],nTailleItem-nPos) FIN RENVOYER Vrai FIN
Exemple 2
Le résultat de l’exemple ci-dessous donnera (le séparateur fonctionne tant pour exploiter la chaîne de référence que pour séparer les éléments dans le tableau final) :
ABC
DEF
GHI
ABC,DEF
ABC,GHI
DEF,GHI
ABC,DEF,GHI
tabRésultat est un tableau de chaînes = Combinaison("ABC,DEF,GHI",",")
PROCÉDURE Combinaison(sRéférence est une chaîne,sSéparateur est une chaîne) : tableau de chaîne tabRes,tabTemp,tabRéférence sont des tableaux de chaînes sCombinaison est une chaîne ChaîneVersTableau(sRéférence,tabRéférence,sSéparateur) tabRes = tabRéférence //au moins une fois chaque élément de la référence POUR nRéférence = 1 _À_ tabRéférence..Occurrence //prendre les éléments dans le résultat pour faire d'autres résultat en ajoutant, s'il n'existe pas, un élément de référence POUR nRésultat = 1 _À_ tabRes..Occurrence SI Position(tabRes[nRésultat],tabRéférence[nRéférence])<1 ALORS //pas de doublon d'élément sCombinaison=tabRes[nRésultat]+sSéparateur+tabRéférence[nRéférence] ChaîneVersTableau(sCombinaison,tabTemp,sSéparateur);TableauTrie(tabTemp);sCombinaison=TableauVersChaîne(tabTemp,sSéparateur) //pas de doublon de combinaison SI TableauCherche(tabRes,tcLinéaire,sCombinaison)<1 ALORS TableauAjoute(tabRes,sCombinaison) FIN FIN FIN RENVOYER tabRes