Last active
April 14, 2021 10:39
-
-
Save tylerburdsall/e00a37bb025652df3c999afdad5581e1 to your computer and use it in GitHub Desktop.
RandomIterator - A C++ iterator-like class that can generate random, unique, and evenly-distributed numbers with O(1) memory space
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* RandomIterator - (c) Tyler Burdsall 2018 | |
* | |
* A C++ class that can generate random, unique, and evenly-distributed | |
* numbers with O(1) memory space. | |
*/ | |
#include <vector> | |
#include <random> | |
#include <iostream> | |
#include <stdexcept> | |
using std::mt19937_64; | |
using std::random_device; | |
using std::uniform_int_distribution; | |
using std::vector; | |
using std::cout; | |
using std::cerr; | |
using std::endl; | |
using std::out_of_range; | |
// We'll use this class to generate random numbers | |
class RandomIterator | |
{ | |
public: | |
/* Constructor for RandomIterator class. | |
* Parameters: | |
* - amount => Amount of numbers to generate | |
* - min => Minimum number in range to generate | |
* - max => Maximum number in range to generate | |
* | |
* The constructor also instanstiates the variable gen | |
* with a new random_device. | |
*/ | |
RandomIterator(const unsigned long long &amount, const unsigned long long &min, const unsigned long long &max): gen((random_device())()) | |
{ | |
floor = min; | |
num_left = amount; | |
last_k = min; | |
n = max; | |
} | |
// Return a bool to determine if there are any numbers left to generate | |
const bool has_next(void) | |
{ | |
return num_left > 0; | |
} | |
// Generate the next random number | |
const unsigned long long next(void) | |
{ | |
if (num_left > 0) | |
{ | |
// Partition the range of numbers to generate from | |
unsigned long long range_size = (n - last_k) / num_left; | |
// Initialize random generator | |
uniform_int_distribution<unsigned long long> rnd(floor, range_size); | |
// Generate random number | |
unsigned long long r = rnd(gen) + last_k + 1; | |
// Set last_k to r so that r is not generated again | |
last_k = r; | |
num_left--; | |
return r; | |
} | |
else | |
{ | |
throw out_of_range("Exceeded amount of random numbers to generate."); | |
} | |
} | |
private: | |
unsigned long long floor; | |
unsigned long long n; | |
unsigned long long last_k; | |
unsigned long long num_left; | |
mt19937_64 gen; | |
}; | |
int main() | |
{ | |
// Amount to create; | |
unsigned long long amount = 100000; | |
// Generate a number from 1 to 1,000,000 | |
unsigned long long min = 1; | |
unsigned long long max = 1000000; | |
// If the amount is greater than the max then this will fail | |
if (amount > max) | |
{ | |
cerr << "Amount must be less than max." << endl; | |
return -1; | |
} | |
// Instantiate iterator | |
RandomIterator iterator(amount, min, max); | |
// While there are still numbers left to generate, | |
// generate and display the numbers | |
while(iterator.has_next()) | |
{ | |
cout << iterator.next() << " "; | |
} | |
cout << endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
how can I generate random numbers using this without being sorted?