Como reiniciar o loop em C ++ (Finding única Sequence Sobre aleatoriamente Executa)

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

  •  03-07-2019
  •  | 
  •  

Pergunta

Os seguintes códigos tentar gerar seqüências aleatórias sobre K é executado. Mas queremos que as cordas recém-gerados para ser totalmente diferente com sua seqüência de referência.

Para que eu tentei usar "continuar" para reiniciar o aleatório processo de geração de string. No entanto, não parece trabalho. O que há de errado com a minha abordagem a seguir?

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

Solução

Seu código parece bem à primeira vista, a menos que eu estou faltando uma grande parte de suas necessidades. Leia este antes de usar rand(). Exceto, é claro, a parte continue. O que você está tentando fazer é ver se este é o mesmo que o initVector ou não, certo? Uma simples comparação faria antes de empurrá-lo ou imprimir para o 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;
}

A variável sameCount é inicializado cada vez que você criar uma nova entrada para o newString e sai do escopo no } fechamento do loop for. Assim, não será incrementado de funcionar como uma verificação adequada contra a geração duplicado. Você deve idealmente, usar um std::set e manter inserindo nele. Duplicatas não são permitidas e você está salvo de um monte de problemas.

Mais sobre o uso rand() srand() e geração de números aleatórios:

Desde o FAQ comp.lang.c:

[...] os bits de baixa ordem de muitos geradores de números aleatórios são distressingly não aleatória

Se você quiser manter seus números randome na faixa

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

um método melhor em comparação com o rand() % N simples (como recomendado no link) é usar o seguinte:

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

Agora, se você fosse para executar o programa, cada vez que você vai ter o mesmo conjunto de 10000 filamentos de DNA aleatórias ímpares. Acontece que isso é porque:

É uma característica da maioria dos geradores de números pseudo-aleatórios (e uma propriedade definida do rand biblioteca C) que eles sempre começam com o mesmo número e passe pela mesma seqüência.

FAQ de comp.lang.c.

Para obter diferentes vertentes entre corridas tente o seguinte:

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

Outras dicas

Seu algoritmo é falso. Tudo o que você está tentando fazer, você não está fazendo isso, e porque não há um único comentário lá, eu realmente não posso dizer onde você errou.

O loop 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

Somando a isso, o seu "newString" não é uma string em tudo, mas um vetor de strings.

Então, o problema não é nem mesmo o uso de continue, é que seu algoritmo é FUBAR.

continue não pular a parte incremento do loop for. Tudo que faz é ir diretamente a ele, ignorando o resto do corpo do loop.

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

No barra invertida na printf() desde que eu não conseguia descobrir como fazer com que o editor de texto, deixe-me escrever um. :)

Você percebeu que sameCount nunca se torna mais de 1? Desde initVec.size () é maior do que 1 execução nunca bate continuar.

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 outros já disse que é difícil descobrir qual era a sua intenção com este código. Você poderia nos dizer por favor, como é que você quer dizer "totalmente diferente", por exemplo?

dirkgentlys resposta é bastante abrangente para o que eu estava tentando dizer agora.

Eu gostaria de recomendar que você não use continuam porém, a maioria padrões de codificação recomendo contra o uso de continuar por um bom motivo, pois faz o controle de fluxo mais difícil de seguir.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top