melt日記 - random_range_generator
C++0xのTR1(Technical Report1)ライブラリには
擬似乱数生成のためのクラスが多数用意されている
今回は、それらの擬似乱数生成器を使用したコンテナの並び替えを実装する
TR1の原型であるBoost C++ Librariesが提供している擬似乱数ライブラリには
random_number_generatorという便利なクラスがある
だが、TR1にはrandom_number_generatorが含まれないので、簡単だがこれを実装してみよう
template <class Engine, class ArgumentType=long> class random_number_generator { Engine& engine_; public: random_number_generator(Engine& engine) : engine_(engine) {} ArgumentType operator()(ArgumentType value) { return engine() % value; } };
次に、TR1の擬似乱数生成器を使用したrandom_shuffleを実装する
(毎回EngineとGeneratorの変数を作るのがめんどくさいから作ったもの)
#include <algorithm> // std::random_shuffle template <class Iterator, class Engine> inline void random_shuffle_for_engine(Iterator first, Iterator last, Engine& engine) { random_number_generator<Engine> gen(engine); std::random_shuffle(first, last, gen); }
これで準備OK
使い方は以下のようになる
#include <ctime> #include <vector> #include <random> // mt19937 using namespace std; using namespace std::tr1; // VC++9.0では必要, C++0xではTR1はstdネームスペースなのでこの行は不要 int main() { vector<int> v; // メルセンヌ・ツイスターを使用してランダムに並び替え mt19937 mt(static_cast<unsigned int>(time(0))); random_shuffle_for_engine(v.begin(), v.end(), mt); return 0; }
※私が作ったRange STLアルゴリズムを使用して以下のように実装してもいい
#include <shand/algorithm.hpp> // shand::random_shuffle template <class Container, class Engine> inline void random_shuffle_for_engine(Container& c, Engine& engine) { random_number_generator<Engine> gen(engine); shand::random_shuffle(c, gen); }
vector<int> v; mt19937 mt(static_cast<unsigned int>(time(0))); random_shuffle_for_engine(v, mt);
※一時オブジェクトを非const参照で渡していたのを修正
※random_number_generatorを簡単に作りすぎたので後ほど修正してエントリ書きます