Как перезапустить цикл в C ++ (поиск уникальной последовательности в случайном порядке)

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

  •  03-07-2019
  •  | 
  •  

Вопрос

Следующие коды пытаются сгенерировать случайные строки на K серий. Но мы хотим, чтобы вновь сгенерированные строки были совершенно другими с его ссылочной строкой.

Для этого я попытался использовать " продолжить " перезапустить случайное процесс генерации строки. Однако это не похоже на работу. Что не так с моим подходом ниже?

#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;
}
Это было полезно?

Решение

Ваш код на первый взгляд выглядит хорошо, если я не пропущу большую часть ваших требований. Прочтите эту перед использованием rand () . За исключением, конечно, части continue . То, что вы пытаетесь сделать, это посмотреть, совпадает ли это с initVector или нет, верно? Простое сравнение можно выполнить до того, как вы вставите его или напечатаете на консоли.

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

Переменная sameCount инициализируется каждый раз, когда вы создаете новую запись в newString , и выходит из области видимости при закрывающем } Цикл для . Таким образом, он не будет увеличен, чтобы функционировать как надлежащая проверка на наличие дубликатов. В идеале вы должны использовать std :: set и продолжать вставлять в него. Дубликаты не допускаются, и вы избавлены от многих неприятностей.

Подробнее об использовании rand () srand () и генерации случайных чисел:

Из FAQ по comp.lang.c:

  

[...] младшие биты многих генераторов случайных чисел являются крайне неслучайными

Если вы хотите, чтобы ваши случайные числа находились в диапазоне

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

лучший способ по сравнению с простым rand ()% N (как указано в ссылке) заключается в использовании следующего:

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

Теперь, если вы запустите свою программу, каждый раз вы будете получать один и тот же набор из 10000 нечетных случайных цепей ДНК. Оказывается, это потому, что:

  

Для большинства генераторов псевдослучайных чисел (и определенного свойства rand библиотеки C) характерно, что они всегда начинаются с одного и того же числа и проходят одну и ту же последовательность.

из другого часто задаваемых вопросов comp.lang.c.

Чтобы получить разные нити на разных участках, попробуйте следующее:

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

Другие советы

Ваш алгоритм фальшивый. Что бы вы ни пытались сделать, вы этого не делаете, и поскольку там нет ни одного комментария, я не могу точно сказать, где вы ошиблись.

Ваш внутренний цикл:

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

Кроме того, ваша " newString " это не строка, а вектор строк.

Итак, ваша проблема даже не в использовании continue , а в том, что ваш алгоритм FUBAR.

continue не пропускает увеличивающуюся часть цикла for . Все, что он делает, это идет прямо к нему, пропуская остальную часть тела цикла.

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

эквивалентно

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

В printf () отсутствует обратная косая черта, так как я не мог понять, как сделать так, чтобы текстовый редактор позволял мне печатать один. :)

Вы поняли, что sameCount никогда не становится больше 1? Поскольку initVec.size () больше 1, выполнение никогда не продолжается,

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

Как уже говорили другие, с этим кодом сложно понять, что вы хотели сделать. Не могли бы вы сказать нам, пожалуйста, как вы имеете в виду «совершенно другой»? например?

Ответ dirkgentlys довольно исчерпывающий для того, что я пытался сказать сейчас.

Я хотел бы порекомендовать вам не использовать continue, поскольку большинство стандартов кодирования рекомендуют не использовать continue по уважительной причине, поскольку это усложняет контроль за потоком.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top