|
|
|
|
Bonjour,
je voudrais m'inspirer du programme de mamiemando (voir le sujet Comptabiliser des permutations en C++ dans ce même forum) qui est très rapide pour essayer de faire une liste de permutations avec répetitions.
Je m'explique:
étant donnés un nombre n et un alphabet Z constitué seulement de 4 lettres tel que Z= {A,T,G,C},
produire toutes les chaines de caractères de longueur n=10 pris parmis l'alphabet Z.
Un exemple avec Z = {A, C} et n = 3 nous donnerait un total de 9 motifs:
aaa
aac
aca
caa
acc
cac
cca
ccc
Pour augmenter la rapidité du code on pourrait aussi assigner à chaque lettre A,T,G,C une valeur binaire:
00,01,10,11.
Puis ensuite refaire la reconversion en lettres après les boucles de traitement.
On a alors 2^(2n) motifs en binaire et 4^n motifs en lettres après conversion.
Pouvez-vous m'aider SVP ?
Configuration: Windows XP Internet Explorer 6.0
[code]
|
Pour les personnes qui tomberaient sur ce fil, je précise que le programme évoqué par mslider est ici :
if (marked[i]) continue; Ainsi, cette ligne interdit d'avoir deux fois le même chiffre dans une combinaison (ce qui exclue des combinaisons comme 1223, 1111 etc...). Si toi au contraire tu les veux, il suffit de commenter cette ligne, et du coup tu peux te passer du vecteur marked : #include <vector>
#include <iostream>
#define TAILLE_ALPHABET 4
char int_to_char(short x){
if (x == 0) return 'A';
else if (x == 1) return 'T';
else if (x == 2) return 'G';
else if (x == 3) return 'C';
return '?';
}
void f(
unsigned prof, // la profondeur courante (nombre de chiffre choisis)
const unsigned & prof_max, // la profondeur max (nombre de chiffre à choisir)
std::vector<short> perm, // la permutation courante
// std::vector<bool> marked, // les nombres utilisés
unsigned & compteur // le nombre de permutations rencontrées
){
if (prof < prof_max){
for(unsigned i=0;i<TAILLE_ALPHABET;++i){
// if (marked[i]) continue;
std::vector<short> perm_suivant = perm;
perm_suivant.push_back(i);
// std::vector<bool> marked_suivant = marked;
// marked_suivant[i] = true;
// f(prof+1,prof_max,perm_suivant,marked_suivant,compteur);
f(prof+1,prof_max,perm_suivant,compteur);
}
}else{ // le nombre a la taille voulue
for(unsigned i=0;i<perm.size();++i) std::cout << int_to_char(perm[i]);
std::cout << std::endl;
++compteur;
}
}
void perm(const unsigned & prof_max){
std::vector<short> perm0;
// std::vector<bool> marked0(TAILLE_ALPHABET,false);
unsigned compteur = 0; // partagé par tous les appels recursifs
// f(0,prof_max,perm0,marked0,compteur);
f(0,prof_max,perm0,compteur);
std::cout << "compteur = " << compteur << std::endl;
}
int main(){
perm(2);
return 0;
}
ce qui donne :
AA AT AG AC TA TT TG TC GA GT GG GC CA CT CG CC compteur = 16 Note : sur CCM les balises de codes sont entre <>, tu as également un bouton prévu pour au-dessus de la boîte dans laquelle tu tapes ton texte Bonne chance |
J'avais pensé à faire des boucles au départ avec ce programme qui d'ailleurs n'est pas complet:
void generateNeighbours(int motifwidth, string m, int nn)
{
int i, j, k, l; string strmotif;
vector < int > motif;
vector < int > neigh;
vector < vector <int> > partial;
for(i = 0; i < m.size(); i++)
{
string base = m.substr(i,1);
motif.push_back(checkBase(base));
}
original = m;
nemotifs.push_back(m);
neighbours.push_back(motif);
neigh = motif;
if(nn == 1 || nn == 2)
{
for(k = motifwidth-1; k >= 0; k--)
{
for(j = 0; j <= 3; j++)
{
neigh[k] = j;
if(neigh != motif)
{
neighbours.push_back(neigh);
partial.push_back(neigh);
for(int g = 0; g < neigh.size(); g++)
{
strmotif += nucleotideUnhash(neigh[g]);
}
nemotifs.push_back(strmotif);
strmotif.clear();
}
}
neigh = motif;
}
}
if(nn == 2)
{
for(i = 0; i < partial.size(); i++)
{
neigh = partial[i];
for(k = motifwidth-1; k >= 0; k--)
{
for(j = 0; j <= 3; j++)
{
neigh[k] = j;
if(neigh != partial[i])
{
neighbours.push_back(neigh);
for(int g = 0; g < neigh.size(); g++)
{
strmotif += nucleotideUnhash(neigh[g]);
}
nemotifs.push_back(strmotif);
strmotif.clear();
}
}
neigh = partial[i];
}
}
}
checkMotifs();
}
mais après avoir vu le programme de mamiemando plus astucieux je me suis arrêté dans mon élan. en plus il est rapide j'ai fais un test pour une profondeur de 10 soit 4^10 combinaisons, le temps de calcul = 23 secondes ! Qui dit mieux ? Merci à toi mamiemando pour ton aide précieuse. |
De rien :-)
|