2009-03-05 7 views
1

次のコードは、K回の実行でランダムな文字列を生成しようとしています。 しかし、新しく生成された文字列は、参照文字列と全く異なるようにしてください。 C++でループを再開する方法(ランダム実行で一意のシーケンスを見つける)

私は、「 」文字列生成プロセスを再開するために「続行」を使用しようとしました。しかし、それは動作していないようです。 私のアプローチでは何が問題になっていますか?

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

あなたのdesriptionは、 "新しく生成された文字列を参照文字列と完全に異なるようにしたい"と言います。コードは "新しい文字列が参照文字列と同じかどうか"をチェックしたいと思うようです。 – NotJarvis

+0

あなたが 'rand()%M'を実行すると、あなたは一様な分布を得ていないことを指摘するべきです(私はこれがあなたが望むものだと思います)。 – Ismael

+0

正しい式は '(rand()/(double)RAND_MAX)*(M-1)'であり、RAND_MAXで除算して0と1の間の一様な値を得てからM-1を掛けて0とM-1。 – Ismael

答えて

4

あなたの要件の大部分が欠落していない限り、コードは最初の一見でうまく見えます。 rand()を使用する前にthisをお読みください。もちろん、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に新しいエントリを作成し、forループの閉鎖}でスコープの外に出るたびに初期化されます。したがって、複製世代に対する適切なチェックとして機能するようにインクリメントされません。理想的には、std::setを使用して、それに挿入してください。重複は許されず、多くの問題から救われます。多くの乱数発生器の下位ビットは痛ましいである[...]

をcomp.lang.cのFAQから:rand()srand()と乱数発生の使用に関する

詳細非ランダム

あなたが範囲でごrandome番号を保持したい場合は

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

シンプルrand() % Nは(リンクに助言として)以下を使用することであると比べて、より良い方法:あなたがあなたのプログラムを実行した場合、今

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

、あなたがの同じセットを取得しますたびに10000個の奇数ランダムDNA鎖。

ほとんどの擬似乱数ジェネレータ(およびCライブラリの定義済みプロパティ)の特徴は、常に同じ番号から始まり同じシーケンスを実行することです。

他のものからFAQのcomp.langc.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; 
} 
+0

失敗はcontinueと関係があります。 jがインクリメントされてj = initvec.size()になります。内部ループの開始時に、内部ループの終了条件に達していない。 – NotJarvis

+0

j == 4のとき、内側のループが終了します。 – dirkgently

+0

正しい - 私はばかだが、newstringが参照と一致するかどうかにかかわらず、newstringはまだコンソールに出力されます。 – NotJarvis

1

continueforループのインクリメント部分をスキップしません。それはループの本体の残りの部分をスキップして、直接それに行きます。

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

に相当します。私は、テキストエディタは、私は1を入力してみましょう作成する方法を見つけ出すことができなかったので、

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

printf()んのバックスラッシュ。 :)

+0

sameCount == initVec.size()は、newStringに追加されるすべての文字に対して常に0に再初期化されるため、決して満たされません。したがって、継続は有効になりません。 – dirkgently

1

dirkgentlysの答えは私が今言おうとしていたもののためにかなり包括的です。

私は、あなたが続行しても使用しないことをお勧めします。ほとんどのコーディング標準は、フロー制御がより困難になるので、良い理由のためにcontinueを使用することをお勧めします。

2

あなたのアルゴリズムは偽造品です。あなたがしようとしていることは何でも、あなたはそれをやっていないし、そこに一つのコメントがないので、あなたがどこに間違って行ったのかは分かりません。

あなたの内部ループ:

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です。

+0

C++初心者のようです。これらのことが起こります。あなたは少し下をトーンにすることができます:) – dirkgently

+0

まあ、彼は彼のアルゴリズムではなく、彼が飛んだ。 ;-)私は、このようなコードを「プロフェッショナル」と呼んでいることは数回あると思います。「継続」を正しく使用する方法や、それを完全に避ける方法を指摘したいと思いましたが、そのアルゴリズムでは...: -/ – DevSolar

1

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

すでにこのコードをあなたの意図したものを見つけることは困難であると述べました。たとえば、「まったく違う」という意味はどうですか?

+0

は、すでにこれを指摘しています。 – NotJarvis

関連する問題