Cómo reiniciar el bucle en C ++ (Encontrar una secuencia única en ejecuciones aleatorias)

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

  •  03-07-2019
  •  | 
  •  

Pregunta

Los siguientes códigos intentan generar cadenas aleatorias sobre K ejecuciones. Pero queremos que las cadenas recién generadas sean totalmente diferentes con su cadena de referencia.

Para eso intenté usar " continuar " para reiniciar el azar proceso de generación de cadenas. Sin embargo, no parece funcionar. ¿Qué tiene de malo mi enfoque a continuación?

#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;
}
¿Fue útil?

Solución

Su código se ve bien a primera vista, a menos que falte una gran parte de sus requisitos. Lea esto antes de usar rand () . Excepto, por supuesto, la parte continue . Lo que intenta hacer es ver si esto es lo mismo que el initVector o no, ¿verdad? Una comparación simple sería suficiente antes de empujarla o imprimirla en la consola.

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 variable sameCount se inicializa cada vez que crea una nueva entrada en newString y queda fuera de alcance en el } de cierre del para loop. Por lo tanto, no se incrementará para funcionar como una verificación adecuada contra la generación duplicada. Lo ideal sería utilizar un std :: set y seguir insertándolo. Los duplicados no están permitidos y estás salvado de muchos problemas.

Más información sobre el uso de rand () srand () y generación de números aleatorios:

De las preguntas frecuentes de comp.lang.c:

  

[...] los bits de orden inferior de muchos generadores de números aleatorios son terriblemente no aleatorios

Si desea mantener sus números aleatorios en el rango

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

un método mejor en comparación con el simple rand ()% N (como se recomienda en el enlace) es utilizar lo siguiente:

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

Ahora, si tuviera que ejecutar su programa, cada vez que obtenga el mismo conjunto de 10000 cadenas de ADN aleatorias impares. Resulta que esto es porque:

  

Es una característica de la mayoría de los generadores de números pseudoaleatorios (y una propiedad definida del rand de la biblioteca C) que siempre comienzan con el mismo número y pasan por la misma secuencia.

de otro Preguntas frecuentes de comp.lang.c.

Para obtener diferentes hebras entre ejecuciones, intente lo siguiente:

#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;
}

Otros consejos

Su algoritmo es falso. Lo que sea que esté tratando de hacer, no lo está haciendo, y debido a que no hay un solo comentario allí, realmente no puedo decir dónde se equivocó.

Tu 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

Agregando a eso, su " newString " no es una cadena en absoluto, sino un vector de cadenas.

Por lo tanto, su problema no es ni siquiera el uso de continue , sino que su algoritmo es FUBAR.

continue no omite la parte de incremento del para . Todo lo que hace es ir directamente a él, omitiendo el resto del cuerpo del bucle.

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

Es equivalente a:

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

No hay barra invertida en printf () , ya que no pude averiguar cómo hacer que el editor de texto me permita escribir uno. :)

¿Te has dado cuenta de que sameCount nunca se convierte en más de 1? Dado que initVec.size () es mayor que 1, la ejecución nunca continúa.

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;
    }

Como ya han dicho otros, es difícil averiguar cuál era su intención con este código. ¿Podría decirnos, por favor, cómo se refiere a "totalmente diferente"? por ejemplo?

La respuesta de

dirkgently es bastante completa para lo que intentaba decir ahora.

Me gustaría recomendar que no use continuar, sin embargo, la mayoría de los estándares de codificación recomiendan no usar continuar por una buena razón, ya que hace que sea más difícil seguir el control de flujo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top