2016-12-07 8 views
0

反復せずにランダムな文字(文字)をm個選んで完全にスタックしておく必要があります。コードを修正するにはどうしたらいいですか?これを修正する方法さえありますか、私はちょうどこのアイデアを破棄して、いくつかのkinfのチュートリアルから解決策を探すべきですか?反復せずにランダムなキャラクタを選ぶC++

#include <iostream> 
#include <ctime> 
#include <cstdlib> 
#include <string> 

using namespace std; 

int main() 
{ 
    cout << "number below 27" << endl; 
    int m; 
    cin >> m; 

    srand(time(NULL)); 
    bool repeat = false; 
    char letters[m]; 
    char letter; 
    for(int i = 0; i < m; i++){ 
    letter = rand()%26 +97; 
    repeat = true; 
    for(int j = 0; j < m; j++){ 
     if(letters[m] == letters[j]){ 
     repeat = false; 
     break; 
     } 
    } 
    if(repeat){ 
     letters[m] = letter; 
    } 
    } 
    for (int i = 0; i < m; i++){ 
    cout << letters[m]; 
    } 
} 
+2

'char letters [m];' VLAは標準のC++ではありません。代わりに 'std :: vector 文字(m);'を使用してください。 –

+0

それは、私たちがC++のバティックを学んでいる間にこの問題に取り組むように頼まれたことです。 – BigPaws

+1

言われたように、それは標準的なC++コードではありません。 –

答えて

3

あなたはsuffleを使用することができます -

#include <random> 
#include <iostream> 
#include <algorithm> 
#include <vector> 

using namespace std; 

int main() 
{ 
    char charSet[]={'a','b','c'};//You can add all the charecters 
    std::random_device rd; 
    std::mt19937 g(rd()); 
    std::shuffle(charSet,charSet+3,g); 
    for(auto c : charSet) 
    { 
    std::cout<<c; 
    } 
    std::cout<<endl; 
    return 0; 
} 
0

あなたのコードのロジックで明らかにエラーがあります:あなたが繰り返しをテストするときにのみ、最後の手紙を越えると比較ではなく、すべての人々に、これまでサンプリングされています。これはあなたがするよう求めてきたものを行うための最も効率的な方法ではありませんが、正しいテストが

for(int i = 0; i < m; i++) { 
    bool repeating;   
    char tryletter; 
    do { 
     tryletter = rand()%26 +97; 
     repeating = false; 
     for(auto j=0; j!=i && !repeating; ++j) 
     repeating = tryletter == letters[j]; 
    } while(repeating); 
    letters[i] = tryletter; 
    } 

だろう。より効率的な方法は、すべての26文字から始まり、ランダムに1つを選択してセットから削除し、次にランダムな文字を選択して削除し続けます。あなたはユニークな乱数を持つまで例

std::string random_letters_without_repetition(std::size_t m) 
{ 
    std::string letters; 
    std::string all = "abcdefghijklmnopqrstuvwxyz"; 
    assert(m <= all.size()); 
    std::random_device r; 
    std::default_random_engine rng(r()); 
    while(m--) { 
    std::uniform_int_distribution<std::size_t> uni{0,all.size()-1}; 
    auto index = uni(rng); 
    letters += all[index]; 
    all.erase(index); 
    } 
    return letters; 
} 
0
bool repeat = false; 
vector<char> letters(m); 
char letter; 
for(int i = 0; i < m; i++){ 
    do 
    { 
     repeat = false; 
     letter = rand()%26 +97; // generate new random number 
     for(int j = 0; j<=i; j++) // iterate through the already generated numbers 
     { 
      if (letter == letters[j]){ // if the generated number already exists, do the while again 
       repeat = true; 
       break; 
      } 
     } 
    } while(repeat); 
    letters[i] = letter; // assign the unique number 
    cout << letter; 
    repeat = false; 
} 

のためにあなたは、乱数ジェネレータを繰り返します。 そしてmは定数と範囲外であるため、出力に自分の価値観は、私を使用します。

for (int i = 0; i < m; i++){ 
    cout << letters[i]; 
} 
+0

私はこのソリューションに固執しようと思います、ありがとう、それは理にかなっています! – BigPaws

+0

@BigPawsようこそ。これがあなたの選択の答えであれば、upvoteまたはacceptがうまくいくでしょう; – izlin

0

私は直接法は、C++でsetを使用することだと思います。次の解決策は、今度はsetを使用して、一意であることを保証します。それが役立つことを願っています。

#include <iostream> 
#include <ctime> 
#include <set> 
#include <random> 

using namespace std; 

int main() 
{ 
    cout << "number below 27" << endl; 
    int m; 
    cin >> m; 

    srand(time(NULL)); 
    set<char> letters_set; 
    while(letters_set.size() < m){ 
     char c = rand()%26+'a'; 
     letters_set.insert(c); 
    } 
    for(auto c: letters_set) 
     cout<<c<<endl; 
} 

さらに効率的なソリューションで、各文字の均等な可能性を保証します。

#include <iostream> 
#include <ctime> 
#include <set> 
#include <random> 

using namespace std; 

int main() 
{ 
    cout << "number below 27" << endl; 
    int m; 
    cin >> m; 
    srand(time(NULL)); 
    vector<int> all_letters(26, 'a'); 
    for(int i = 0; i < 26; ++i) all_letters[i] += i; 
    vector<char> letters_set; 
    for(int i = 0; i < m; ++i){ 
     int select = rand()%all_letters.size(); 
     letters_set.push_back(all_letters[select]); 
     all_letters.erase(all_letters.begin()+select); 
    } 
    for(auto c: letters_set) 
     cout<<c<<endl; 
} 
+0

これはどのように繰り返しを避けますか? – Walter

+0

@walter: 'std :: set'を使用しますが、順序は固定されており、ランダムではありません。 – Jarod42

+0

@Walter最初の解決策は繰り返しを避けるために 'set'を使用していますが、2番目の解決策として回避できる衝突がたくさんあるので非常に非効率的です。 – Hearen

関連する問題