I have this algorithm for shuffling, I am trying to replace the Rand with Mersenne as an enhancement since Mersenne is more efficient and produces much randomness compared to rand according to what I've searched. However, when comparing it side by side, I ran it for 5 times each and total the repetitions of each 5 cases, I get more repetition when using Mersenne than in Rand. Why is that? I'm new to programming, your help is appreciated. Thank you!
This is my code for using Mersenne
#include <iostream>
#include <vector>
#include <random>
#include <chrono>
struct Element {
int value;
std::string attribute1;
std::string attribute2;
std::string attribute3;
std::string attribute4;
std::string attribute5;
int count;
};
bool haveSameAttributes(const Element& elem1, const Element& elem2) {
return (elem1.attribute1 == elem2.attribute1 &&
elem1.attribute2 == elem2.attribute2 &&
elem1.attribute3 == elem2.attribute3 &&
elem1.attribute4 == elem2.attribute4 &&
elem1.attribute5 == elem2.attribute5);
}
void enhancedShuffle(std::vector<Element>& rndnum, std::mt19937& gen) {
int n = rndnum.size();
int n1 = n;
int j = n - 1;
int attempts = 0;
const int max_attempts = n1; // Maximum number of attempts allowed
// Reset the count for all elements to 0
for (Element& elem : rndnum) {
elem.count = 0; // Assuming count is a member variable of Element
}
for (int i = 0; i < n; ++i) {
// Using Mersenne Twister PRNG
std::uniform_int_distribution<> dist(0, n1 - 1);
int x = dist(gen);
rndnum[x].count++;
if (i > 0) {
// Check Element's Attributes (5) & Max Attempt to n1
if ((rndnum[x].value == rndnum[j + 1].value || haveSameAttributes(rndnum[x], rndnum[j + 1])) && attempts < max_attempts) {
int z = dist(gen);
++attempts;
// Compare Selection Count of Elements
if (rndnum[x].count > rndnum[i - 1].count && attempts < max_attempts) {
// Using Mersenne Twister PRNG
x = dist(gen);
++attempts;
rndnum[x].count++;
}
if ((x + z) >= j) {
x = (x + z) - j;
} else {
x = x + z;
}
}
}
std::swap(rndnum[x], rndnum[j]);
--n1;
--j;
}
}
// For counting the repetitions throughout the shuffled list
int countConsecutiveRepetitions(const std::vector<Element>& rndnum) {
int consecutiveRepetitions = 0;
for (size_t i = 1; i < rndnum.size(); ++i) {
if (haveSameAttributes(rndnum[i], rndnum[i - 1])) {
++consecutiveRepetitions;
}
}
return consecutiveRepetitions;
}
std::vector<int> countConsecutiveRepetitionsPerAttribute(const std::vector<Element>& rndnum) {
int consecutiveRepetitions1 = 0;
int consecutiveRepetitions2 = 0;
int consecutiveRepetitions3 = 0;
int consecutiveRepetitions4 = 0;
int consecutiveRepetitions5 = 0;
for (size_t i = 1; i < rndnum.size(); ++i) {
if (rndnum[i].attribute1 == rndnum[i - 1].attribute1) {
++consecutiveRepetitions1;
}
if (rndnum[i].attribute2 == rndnum[i - 1].attribute2) {
++consecutiveRepetitions2;
}
if (rndnum[i].attribute3 == rndnum[i - 1].attribute3) {
++consecutiveRepetitions3;
}
if (rndnum[i].attribute4 == rndnum[i - 1].attribute4) {
++consecutiveRepetitions4;
}
if (rndnum[i].attribute5 == rndnum[i - 1].attribute5) {
++consecutiveRepetitions5;
}
}
int totalConsecutiveAttributes = consecutiveRepetitions1 + consecutiveRepetitions2 + consecutiveRepetitions3 + consecutiveRepetitions4 + consecutiveRepetitions5;
return {consecutiveRepetitions1, consecutiveRepetitions2, consecutiveRepetitions3, consecutiveRepetitions4, consecutiveRepetitions5, totalConsecutiveAttributes};
}
int main() {
const int desiredSize = 50;
const int numIterations = 1000;
std::vector<Element> baseList = {
{1, "Dragon", "Large", "Long", "Shoes", "Green"},
{2, "Dragon", "Small", "Average", "Boots", "Green"},
{3, "Dragon", "Small", "Short", "Slippers", "Red"},
{4, "Dragon", "Medium", "Average", "Shoes", "White"},
{5, "Dragon", "Large", "Long", "Boots", "Red"},
};
int totalConsecutiveRepetitions = 0;
std::vector<int> totalConsecutiveRepetitionsPerAttribute(5, 0);
auto seed = static_cast<unsigned>(std::chrono::high_resolution_clock::now().time_since_epoch().count());
std::mt19937 gen(seed);
for (int iteration = 0; iteration < numIterations; ++iteration) {
std::vector<Element> rndnum;
// Repeat the base list to achieve the desired size
while (rndnum.size() < desiredSize) {
rndnum.insert(rndnum.end(), baseList.begin(), baseList.end());
}
// Trim the excess elements
rndnum.resize(desiredSize);
enhancedShuffle(rndnum, gen);
// Display each element with its attributes (Optional)
// for (const auto& element : rndnum) {
// std::cout << "Value: " << element.value
// << ", Attribute1: " << element.attribute1
// << ", Attribute2: " << element.attribute2
// << ", Attribute3: " << element.attribute3
// << ", Attribute4: " << element.attribute4
// << ", Attribute5: " << element.attribute5
// << ", Count: " << element.count << std::endl;
// }
int consecutiveRepetitions = countConsecutiveRepetitions(rndnum);
totalConsecutiveRepetitions += consecutiveRepetitions;
std::vector<int> consecutiveRepetitionsPerAttribute = countConsecutiveRepetitionsPerAttribute(rndnum);
for (int i = 0; i < 5; ++i) {
totalConsecutiveRepetitionsPerAttribute[i] += consecutiveRepetitionsPerAttribute[i];
}
std::cout << "\nConsecutive repetitions in iteration " << iteration + 1 << ": " << consecutiveRepetitions << std::endl;
std::cout << "---------------------------------------------\n";
}
int totalAttributeCounts = 0;
for (int count : totalConsecutiveRepetitionsPerAttribute) {
totalAttributeCounts += count;
}
std::cout << "\nTotal Consecutive repetitions across all iterations: " << totalConsecutiveRepetitions << std::endl;
return 0;
}
RESULTS: MERSENNE
- CASE 1: 2317
- CASE 2: 2222
- CASE 3: 2325
- CASE 4: 2331
- CASE 5: 2314
Now this is my code for using Rand
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <time.h>
struct Element {
int value;
std::string attribute1;
std::string attribute2;
std::string attribute3;
std::string attribute4;
std::string attribute5;
int count;
};
bool haveSameAttributes(const Element& elem1, const Element& elem2) {
return (elem1.attribute1 == elem2.attribute1 &&
elem1.attribute2 == elem2.attribute2 &&
elem1.attribute3 == elem2.attribute3 &&
elem1.attribute4 == elem2.attribute4 &&
elem1.attribute5 == elem2.attribute5);
}
void enhancedShuffle(std::vector<Element>& rndnum) {
int n = rndnum.size();
int n1 = n;
int j = n - 1;
int attempts = 0;
const int max_attempts = n1; // Maximum number of attempts allowed
// Reset the count for all elements to 0
for (Element& elem : rndnum) {
elem.count = 0; // Assuming count is a member variable of Element
}
for (int i = 0; i < n; ++i) {
// Using Mersenne Twister PRNG
int x = rand() % n1;
rndnum[x].count++;
if (i > 0) {
// Check Element's Attributes (5) & Max Attempt to n1
if ((rndnum[x].value == rndnum[j + 1].value || haveSameAttributes(rndnum[x], rndnum[j + 1])) && attempts < max_attempts) {
int z = rand() % n1;
++attempts;
// Compare Selection Count of Elements
if (rndnum[x].count > rndnum[i - 1].count && attempts < max_attempts) {
// Using Mersenne Twister PRNG
x = rand() % n1;
++attempts;
rndnum[x].count++;
}
if ((x + z) >= j) {
x = (x + z) - j;
} else {
x = x + z;
}
}
}
std::swap(rndnum[x], rndnum[j]);
--n1;
--j;
}
}
// For counting the repetitions throughout the shuffled list
int countConsecutiveRepetitions(const std::vector<Element>& rndnum) {
int consecutiveRepetitions = 0;
for (size_t i = 1; i < rndnum.size(); ++i) {
if (haveSameAttributes(rndnum[i], rndnum[i - 1])) {
++consecutiveRepetitions;
}
}
return consecutiveRepetitions;
}
std::vector<int> countConsecutiveRepetitionsPerAttribute(const std::vector<Element>& rndnum) {
int consecutiveRepetitions1 = 0;
int consecutiveRepetitions2 = 0;
int consecutiveRepetitions3 = 0;
int consecutiveRepetitions4 = 0;
int consecutiveRepetitions5 = 0;
for (size_t i = 1; i < rndnum.size(); ++i) {
if (rndnum[i].attribute1 == rndnum[i - 1].attribute1) {
++consecutiveRepetitions1;
}
if (rndnum[i].attribute2 == rndnum[i - 1].attribute2) {
++consecutiveRepetitions2;
}
if (rndnum[i].attribute3 == rndnum[i - 1].attribute3) {
++consecutiveRepetitions3;
}
if (rndnum[i].attribute4 == rndnum[i - 1].attribute4) {
++consecutiveRepetitions4;
}
if (rndnum[i].attribute5 == rndnum[i - 1].attribute5) {
++consecutiveRepetitions5;
}
}
int totalConsecutiveAttributes = consecutiveRepetitions1 + consecutiveRepetitions2 + consecutiveRepetitions3 + consecutiveRepetitions4 + consecutiveRepetitions5;
return {consecutiveRepetitions1, consecutiveRepetitions2, consecutiveRepetitions3, consecutiveRepetitions4, consecutiveRepetitions5, totalConsecutiveAttributes};
}
int main() {
const int desiredSize = 50;
const int numIterations = 1000;
std::vector<Element> baseList = {
{1, "Dragon", "Large", "Long", "Shoes", "Green"},
{2, "Dragon", "Small", "Average", "Boots", "Green"},
{3, "Dragon", "Small", "Short", "Slippers", "Red"},
{4, "Dragon", "Medium", "Average", "Shoes", "White"},
{5, "Dragon", "Large", "Long", "Boots", "Red"},
};
int totalConsecutiveRepetitions = 0;
std::vector<int> totalConsecutiveRepetitionsPerAttribute(5, 0);
srand(static_cast<unsigned int>(time(nullptr)));
for (int iteration = 0; iteration < numIterations; ++iteration) {
std::vector<Element> rndnum;
// Repeat the base list to achieve the desired size
while (rndnum.size() < desiredSize) {
rndnum.insert(rndnum.end(), baseList.begin(), baseList.end());
}
// Trim the excess elements
rndnum.resize(desiredSize);
enhancedShuffle(rndnum);
// Display each element with its attributes (Optional)
// for (const auto& element : rndnum) {
// std::cout << "Value: " << element.value
// << ", Attribute1: " << element.attribute1
// << ", Attribute2: " << element.attribute2
// << ", Attribute3: " << element.attribute3
// << ", Attribute4: " << element.attribute4
// << ", Attribute5: " << element.attribute5
// << ", Count: " << element.count << std::endl;
// }
int consecutiveRepetitions = countConsecutiveRepetitions(rndnum);
totalConsecutiveRepetitions += consecutiveRepetitions;
std::vector<int> consecutiveRepetitionsPerAttribute = countConsecutiveRepetitionsPerAttribute(rndnum);
for (int i = 0; i < 5; ++i) {
totalConsecutiveRepetitionsPerAttribute[i] += consecutiveRepetitionsPerAttribute[i];
}
std::cout << "\nConsecutive repetitions in iteration " << iteration + 1 << ": " << consecutiveRepetitions << std::endl;
std::cout << "---------------------------------------------\n";
}
int totalAttributeCounts = 0;
for (int count : totalConsecutiveRepetitionsPerAttribute) {
totalAttributeCounts += count;
}
std::cout << "\nTotal Consecutive repetitions across all iterations: " << totalConsecutiveRepetitions << std::endl;
return 0;
}
RESULTS: RAND
- CASE 1: 2292
- CASE 2: 2222
- CASE 3: 2231
- CASE 4: 2243
- CASE 5: 2268
COMPARISON: TOTAL CONSECUTIVE REPETITIONS PER CASE
MERSENNE:
- CASE 1: 2317
- CASE 2: 2222
- CASE 3: 2325
- CASE 4: 2331
- CASE 5: 2314
RAND
- CASE 1: 2292
- CASE 2: 2222
- CASE 3: 2231
- CASE 4: 2243
- CASE 5: 2268
The results for both are inconsistent, there are times when I test again Mersenne seems to be lower and Rand appears higher, but most of the time the Rand has much lower consecutive repetitions. I was expecting to have lower results when using Mersenne. Does that mean that Mersenne is not an enhancement in my application to use?