乱数の生成
参考
こちらのサイトを参考にしました。
色々な乱数が紹介されていましたが、範囲指定の一様乱数の場合は、std::uniform_int_distribution使えば良さそうなので、以下ではこれを使っていきます。
qiita.com
ソースコード
- distの第1引数にminを、第2引数にmaxを設定します。こうすることで、乱数の範囲をmin~maxに制限できます。
- 注意としては、maxはその数値自身も含む点だと思います。他の言語では、min~max-1が生成される場合もある。
#include <iostream> #include <random> int main() { //今回は0~3の範囲で乱数を生成 std::mt19937 mt{ std::random_device{}() }; std::uniform_int_distribution<int> dist(1, 3); //適当に5回ほど生成 for (int i = 0; i < 5; i++) { std::cout << "i = " << i << ", dist(mt) = " << dist(mt) << std::endl; } }
実行結果
i = 0, dist(mt) = 2 i = 1, dist(mt) = 2 i = 2, dist(mt) = 1 i = 3, dist(mt) = 3 i = 4, dist(mt) = 3
乱数配列の生成
乱数配列の生成は先ほどの様にfor文で回して、vectorにでも格納してしまえばよさそうです。
#include <iostream> #include <random> //重複なしの、乱数配列を返す std::vector<int> RandomVec1(int size, int min, int max) { //配列の宣言 std::vector<int> v(size, 0); //乱数生成のための std::mt19937 mt{ std::random_device{}() }; std::uniform_int_distribution<int> dist(min, max); //for文で重複がないかチェックしながら乱数を生成 for (int i = 0; i < v.size(); i++) { v[i] = dist(mt); } return v; } int main(){ //長さ5で、-2~2の乱数を格納する配列を生成 std::vector<int> v1 = RandomVec1(5, -2, 2); //表示 for (int i = 0; i < v1.size(); i++) { std::cout << "v1[" << i << "] = " << v1[i] << std::endl; } }
実行結果
v1[0] = -2 v1[1] = 0 v1[2] = 0 v1[3] = 2 v1[4] = -1
重複なしの乱数配列の生成
重複なしというのがちょっと面倒くさそうです。
と思っていたのですが、std::countという関数を使えば、vectorに指定した要素が含まれているかを確認できるみたいです。
www.techiedelight.com
ソースコード
#include <iostream> #include <random> #include <algorithm> //重複なしの、乱数配列を返す std::vector<int> RandomVec2(int size, int min, int max) { //max-min+1 < sizeだと重複なしの乱数配列の生成が不可なので、exitする if (max - min + 1 < size) { exit(1234); } //配列の宣言 std::vector<int> v(0); //乱数生成のための std::mt19937 mt{ std::random_device{}() }; std::uniform_int_distribution<int> dist(min, max); //for文で重複がないかチェックしながら乱数を生成 for (int i = 0; i < size; i++) { while (true) { //乱数生成 int r = dist(mt); //rがdistに含まれていなかったら、追加してから、whileループを抜ける if (std::count(v.begin(), v.end(), r) == 0) { v.push_back(r); break; } } } return v; } int main(){ //長さ5で、-2~2の乱数を格納する配列を生成 std::vector<int> v1 = RandomVec2(5, -2, 2); //表示 for (int i = 0; i < v1.size(); i++) { std::cout << "v1[" << i << "] = " << v1[i] << std::endl; } //こっちは、max-min+1 < sizeになるため実行されない std::vector<int> v2 = RandomVec2(5, 0, 2); //表示(実行されない) for (int i = 0; i < v1.size(); i++) { std::cout << "v2[" << i << "] = " << v2[i] << std::endl; } }
実行結果
先ほどの違って、重複がないことが確認できます。
v1[0] = 1 v1[1] = 2 v1[2] = -2 v1[3] = 0 v1[4] = -1
選択肢から作成
概要
選択肢をvectorで与えておく方法です。
文字列などで乱数を生成するときに使えると思います。
ソースコード
#include <iostream> #include <random> #include <string> //選択肢から乱数配列を返す template<class T> std::vector<T> RandomVec3(int size, std::vector<T> choices) { //配列の宣言 std::vector<T> v(size); //乱数生成のための std::mt19937 mt{ std::random_device{}() }; std::uniform_int_distribution<int> dist(0, choices.size() - 1); //for文で重複がないかチェックしながら乱数を生成 for (int i = 0; i < v.size(); i++) { v[i] = choices[dist(mt)]; } return v; } int main(){ //選択肢 std::vector<std::string> fruits = { "apple", "banana", "lemon" }; //長さ5で、-2~2の乱数を格納する配列を生成 std::vector<std::string> v1 = RandomVec3<std::string>(6, fruits); //表示 for (int i = 0; i < v1.size(); i++) { std::cout << "v1[" << i << "] = " << v1[i] << std::endl; } }
実行結果
v1[0] = banana v1[1] = apple v1[2] = lemon v1[3] = apple v1[4] = lemon v1[5] = apple