Come riavviare Loop in C ++ (Trovare una sequenza univoca su esecuzioni casuali)

StackOverflow https://stackoverflow.com/questions/614012

  •  03-07-2019
  •  | 
  •  

Domanda

I seguenti codici provano a generare stringhe casuali su K esecuzioni. Ma vogliamo che le stringhe appena generate siano totalmente diverse con la sua stringa di riferimento.

Per questo ho provato a usare " continua " per riavviare il casuale processo di generazione di stringhe. Tuttavia non sembra funzionare. Cosa c'è di sbagliato nel mio approccio di seguito?

#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include <time.h>
using namespace std;


// In this code we want to print new string that is entirely different with  
// with those in initVector 


template <typename T> void  prn_vec(std::vector < T >&arg, string sep="")
{   // simple function for printing vector
    for (int n = 0; n < arg.size(); n++) {
        cout << arg[n] << sep; 
    }
}


int main  ( int arg_count, char *arg_vec[] ) {

    // This is reference string
    vector <string> initVec;
    initVec.push_back("A");
    initVec.push_back("A");
    initVec.push_back("A");
    initVec.push_back("A");

    vector <string> DNA;
      DNA.push_back("A");
      DNA.push_back("C");
      DNA.push_back("G");
      DNA.push_back("T");

    for (unsigned i =0; i< 10000; i++) {

       vector <string> newString;
       for(unsigned j=0; j<initVec.size(); j++) {

         int dnaNo = rand() % 4;
         string newBase = DNA[dnaNo];
         string oldBase = initVec[j];

         int sameCount = 0;
         if (newBase == oldBase) {
            sameCount++;
         }

         if (sameCount == initVec.size()) {
              continue;
         }

         newString.push_back(newBase);

       } 
       cout << "Run " << i << " : ";
       prn_vec<string>(newString);
       cout << endl;

    }

    return 0;
}
È stato utile?

Soluzione

Il tuo codice sembra a prima vista a meno che non mi manchi una gran parte delle tue esigenze. Leggi questo prima di utilizzare rand () . Tranne ovviamente, la parte continue . Quello che stai cercando di fare è vedere se è uguale o meno a initVector , giusto? Un semplice confronto farebbe prima di inserirlo o stampare sulla console.

int sameCount = 0;
if (newBase == oldBase) {
 sameCount++;
}
// sameCount can be 1 at most, 0 otherwise
// this check never return true
if (sameCount == initVec.size()) {
continue;
}

La variabile sameCount viene inizializzata ogni volta che si crea una nuova voce in newString e esce dall'ambito al } di chiusura per loop. Pertanto, non verrà incrementato per funzionare come un controllo adeguato contro la generazione duplicata. Idealmente, dovresti usare un std :: set e continuare a inserirlo in esso. I duplicati non sono consentiti e si viene salvati da molti problemi.

Altre informazioni sull'uso di rand () srand () e generazione di numeri casuali:

Dalle FAQ di comp.lang.c:

  

[...] i bit di ordine basso di molti generatori di numeri casuali sono dolorosamente non casuali

Se vuoi mantenere i tuoi numeri randome nell'intervallo

[0, 1, ... N - 1]

un metodo migliore rispetto al semplice rand ()% N (come consigliato nel link) è utilizzare quanto segue:

(int)((double)rand() / ((double)RAND_MAX + 1) * N)

Ora, se dovessi eseguire il tuo programma, ogni volta otterrai lo stesso set di 10.000 dispari casuali di DNA. Si scopre che ciò è dovuto al fatto che:

  

È una caratteristica della maggior parte dei generatori di numeri pseudo-casuali (e una proprietà definita del rand della libreria C) che iniziano sempre con lo stesso numero e attraversano la stessa sequenza.

da un'altra FAQ di comp.lang.c.

Per ottenere fili diversi tra le corse, provare quanto segue:

#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include <ctime>
#include <cstdlib>
using namespace std;
    int main  ( int arg_count, char *arg_vec[] ) {

    // most pseudo-random number generators 
    // always start with the same number and 
    // go through the same sequence. 
    // coax it to do something different!
    srand((unsigned int)time((time_t *)NULL));

    // This is reference string
    string initVec("AAAA");    
    // the family
    string DNA("ACGT");

    for (unsigned i =0; i< 5; i++) {
       string newString;
       for(unsigned j=0; j<initVec.size(); j++) {
         int dnaNo = (int)((double)rand() / ((double)RAND_MAX + 1) * 4);
         char newBase = DNA[dnaNo];         
         newString += newBase;
       }
               // ideally push in a std::set 
               // for now keep displaying everything
         if (newString != initVec) {
               cout << "Run " << i << " : " << newString << endl; 
            }
         }
     return 0;
}

Altri suggerimenti

Il tuo algoritmo è falso. Qualunque cosa tu stia cercando di fare, non lo stai facendo, e poiché non c'è un singolo commento, non posso davvero dire dove hai sbagliato.

Il tuo ciclo interno:

for each element of initVec (4)
    create a random element
    set sameCount to 0
    if random element == current element of initVec, set sameCount to 1
    if sameCount == 4, do something (pointless as this never happens)
    add random element to newString

Aggiungendo a ciò, il tuo " newString " non è affatto una stringa, ma un vettore di stringhe.

Quindi, il tuo problema non è nemmeno l'uso di continue , è che il tuo algoritmo è FUBAR.

continua non salta la parte incrementale del ciclo per . Tutto ciò che fa è andare direttamente ad esso, saltando il resto del corpo del ciclo.

for(int i = 0; i < 10; i++)
{
  if(i == 3)
    continue;
  printf("%d ", i);
}

È equivalente a:

int i = 0;
while(i < 10)
{
  if(i == 3)
    goto increment;
  printf("%d ", i);
increment:
  i++;
}

Nessuna barra rovesciata nel printf () poiché non sono riuscito a capire come fare in modo che l'editor di testo mi permetta di digitarne uno. :)

Hai capito che sameCount non diventa mai più di 1? Poiché initVec.size () è maggiore di 1, l'esecuzione non ha successo.

int sameCount = 0;
    //sameCount is 0
    if (newBase == oldBase) { // if it is true sameCount is 1
        sameCount++;
    }
    // sameCount is 1 or 0
    if (sameCount == initVec.size()) { //this expression is always false if initVec longer than 1
        continue;
    }

Come altri hanno già detto, è difficile scoprire quale fosse la tua intenzione con questo codice. Potresti dirci per favore come intendi "totalmente diverso" per esempio?

La risposta di dirkgentlys è piuttosto completa per quello che stavo cercando di dire ora.

Vorrei raccomandare di non utilizzare continue, tuttavia, la maggior parte degli standard di codifica sconsiglia di utilizzare continue per buoni motivi poiché rende più difficile il controllo del flusso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top