I am trying to generate a sequence of 6 random numbers with all the numbers being different from each other(no repetition of the numbers). But when I try to test whether I have successfully generated those numbers or not by trying to print them out, the code compiles successfully but nothing appears on the screen. Something seems to be wrong with my use of the function erase() because once I remove it the code produce some output although not what I am looking for.
#include<bits/stdc++.h>
#include<time.h>
using namespace std;
int main(void)
{
srand(time(NULL));
vector<int>v;
vector<int>V;
int arr[6];
int i,j;
for(i=1;i<=6;i++)
{
V.push_back(i);
}
for(int i=0;i<6;i++)
{
cout<<V[i]<<" ";
}
for(int i=0;i<6;i++)
{
int n=rand()%6;
v.push_back(V[n]);
V.erase(V.begin()+n);
}
cout<<endl;
for(int i=0;i<6;i++)
{
cout<<V[i]<<" ";
}
return 0;
}
You are using a wrong algorithm:
Generate six random numbers
If there are some which are equal, do something.
This is better:
Make a full list of all possible numbers.
Take random a number out of that list and remove it from the list. Do this six times.
You should use std::shuffle to re-order your numbers
#include <vector>
#include <iostream>
#include <random>
#include <algorithm>
#include <numeric>
void print_numbers(const std::vector<int> & numbers) {
for (int number : numbers) {
std::cout << number << " ";
}
std::cout << std::endl;
}
int main() {
std::vector numbers(6);
std::iota(numbers.begin(), numbers.end(), 1);
print_numbers(numbers);
std::random_device rd; // ok for small quantities like this, generally prefer a std::default_random_engine with some seed
std::shuffle(numbers.begin(), numbers.end(), rd);
print_numbers(numbers);
}
This question already has answers here:
How to make sure that std::random_shuffle always produces a different result?
(6 answers)
Closed 4 years ago.
Decided to create a deck in C++ using a vector and a Card class. I chose this because shuffling is supposed to be easy using random_shuffle. My first approach just to get aquatint with C++ I made a Card list, used vector to generate numbers and shuffle them just to insert the cards in a tmp list and return it. This was messy to say the least.
So on my second branch I tried to do it with a vector from the start, it looks like this:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
// Represent a card
class Card
{
private:
int suit;
int value;
public:
Card(){}
Card(int v, int s)
{
suit = s;
value = v;
}
void
setNewVals(int v, int s)
{
value = v;
suit = s;
}
int
getValue()
{
return value;
}
int
getSuit()
{
return suit;
}
};
// Shuffle deck
void
shuffleDeck(vector<Card> *c, int shuffles)
{
for(int s = 0; s < shuffles; s++)
{
random_shuffle(c->begin(), c->end());
}
}
int
main()
{
//TODO: Later input from main
int numDecks = 10;
int numShuffles = 10;
// Create a deck vector
vector<Card> c;
// Select card's value
for(int d = 0; d < numDecks; d++)
{
for(int v = 1; v < 14; v++)
{
// Select card's suit
for(int s = 0; s < 4; s++)
{
Card card(v, s);
c.push_back(card);
}
}
}
// Shuffle the deck
shuffleDeck(&c, numShuffles);
// Print out first 52 cards
for(int i = 0; i < 52; i++)
{
Card aCard = c.front();
cout << aCard.getValue() << "\t" << aCard.getSuit() << endl;
c.erase(c.begin());
}
return 0;
}
The problem is that now the random_shuffle does not really work as expected. It shuffles alright, but all cards always end up in the same order. When I did almost the exact same thing with int, it worked fine.
I really have no idea why it is not shuffling random all the time. Have I misinterpreted how vectors work?
You should see http://www.cplusplus.com/reference/algorithm/random_shuffle/ link.
The randomness of std::random_shuffle() seems depends on the std::srand function.
so, you should code like follows (It is just one example)
#include <iostream>
#include <algorithm>
#include <vector>
#include <ctime>
...
int main() {
...
// Make randomness for shuffle
std::srand(unsigned(std::time(0)));
// Shuffle the deck
shuffleDeck(&c, numShuffles);
...
}
In order for std::random_shuffle to return different values at different runs, it needs to be given a non-fixed seed.
You can solve this by adding the line:
std::srand(std::time(NULL));
Now executions at least 1 second apart will give different shuffling results.
I am trying to generate a unique random number between 0 and 9. The same number cannot be generated twice and the function will be ran 9 time (until all the 9 numbers are used.) Here is the latest way I have been trying to do this:
int uniqueRandomInt(int x) {
std::vector<int> usedRandoms;
int random = x;
//Iterate vector
for (unsigned int i = 0; i < usedRandoms.size(); i++) {
//if passed value is in vector
if (random = usedRandoms[i]) {
uniqueRandomInt(random);
}
else {
//If unique rand found put into vector
usedRandoms.push_back(random);
return random;
}
}
}
Calling it in another function using:
cout << uniqueRandomInt(-1) << endl;
Result I am getting is:
17801152 (Changes every time the function is called)
Am I going about this totally wrong? I did try other ways but with no luck and this is where I'm currently at. Thanks in advance.
I prefer to use shuffle.
#include <algorithm>
#include <iostream>
#include <random>
#include <vector>
#include <cassert>
class T455_t
{
private:
// data
std::vector<int> m_iVec ;
public:
T455_t() {}
int exec()
{
std::vector<int> iVec;
gen10();
for (int i=0; i<10; ++i)
{
int nxtRandom = uniqueRandomInt();
std::cout << nxtRandom << std::endl;
}
return(0);
}
private: // methods
void gen10() // fills data attribute with 10 digits
{
for (int i=0; i<=9; ++i)
m_iVec.push_back(i);
std::random_device rd;
std::mt19937_64 gen(rd());
std::shuffle (m_iVec.begin(), m_iVec.end(), gen);
// m_iVec now contains 10 unique numbers,
// range 0..9, in random order
}
int uniqueRandomInt()
{
assert(m_iVec.size());
int retVal = m_iVec.back(); // gets last element in vector
m_iVec.pop_back(); // removes last element
return(retVal);
}
}; // class T455_t
int main(int argc, char* argv[])
{
setlocale(LC_ALL, "");
std::ios::sync_with_stdio(false);
std::chrono::high_resolution_clock::time_point m_start_us =
std::chrono::high_resolution_clock::now();
int retVal = -1;
{
T455_t t455;
retVal = t455.exec();
}
std::chrono::microseconds chrono_duration_us =
std::chrono::duration_cast <std::chrono::microseconds>
(std::chrono::high_resolution_clock::now() - m_start_us);
std::cout << " FINI " << chrono_duration_us.count()
<< " us" << std::endl;
return(retVal);
}
Your function doesn't appear to return a value if usedRandoms.size() is zero, which it will be the first time you call the function
int uniqueRandomInt(int x) {
std::vector<int> usedRandoms; // vector.size() = 0
int random = x;
// for loop won't be entered
for (unsigned int i = 0; i < usedRandoms.size(); i++)
{
}
// function doesn't return a value
}
It's worth noting that it's undefined behaviour to declare a function to return a value, and then not return a value. That's why the random values you're getting.
From the C++ standard, 6.6.3 (emphasis mine):
Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.
vector<int> initVector(){
vector<int> ret;
ret.clear();
for(int i = 0 ; i < 10 ; ++i){
ret.push_back(i);
}
return ret;
}
int uniqueRendom(){
static vector<int> randomNumbers = initVector();
int randomSize = randomNumbers.size() - 1;
if(randomSize <= 0){
return -1;
}
double randomeNum = (double)rand() / INT_MAX;
int randomIndex = (int) (randomeNum * randomSize + 0.5) ;
int returnValue = randomNumbers[randomIndex];
randomNumbers.erase(randomNumbers.begin() + randomIndex);
return returnValue;
}
include limits.h for INT_MAX.
This question already has answers here:
Create Random Number Sequence with No Repeats
(27 answers)
Closed 6 years ago.
I've got a random number generator function ("Rndom (min, max)"),
and I have an int with 4 elements called "Data [3]".
I used the for loop to generate numbers (1-4) to the elements of the "Data" int:
for (int i = 0;i < 3;i++)
{
Data[i] = Rndom(1, 4)
}
How can I prevent that the data gets duplicated element number ?
So, I don't want this: "Data" elements: 1 3 4 1 ("1" is duplicated). I want to make different numbers....
Thank you for the help !
Since you want an array or vector of shuffled integer values, use std::shuffle to shuffle a vector (or whatever) initialized with sequential values.
#include <iostream>
#include <vector>
#include <random>
#include <algorithm>
#include <numeric>
int main() {
std::random_device rd;
std::mt19937 rng(rd()); // seed rng using rd
std::vector<int> data(3); // create a 3-entry vector
std::iota(data.begin(), data.end(), 0); // fill with sequence
std::shuffle(data.begin(), data.end(), rng); // mix entries using rng
// dump the result
for(auto r : data) { std::cout << r << ' '; }
std::cout << '\n';
}
The outputs of 3 executions:
1 0 2
2 1 0
2 0 1
Here is a version which doesn't rely so much on the standard C++ library, and uses the C-runtime's crappy random number generator, just because I didn't have access to Rndom's source code, which is undoubtedly of a proprietary nature, so this is quite understandable:
#include <iostream> // only for std::cout
#include <cstdlib> // for srand, rand
#include <ctime> // for time
namespace shuffle {
using size_t = decltype(sizeof(1));
bool Srndom() {
std::srand(std::time(0));
return true;
}
int Rndom(int low, int high) {
static bool init = Srndom();
return std::rand() % (high - low + 1) + low;
}
template <typename T>
void Shuffle(T* pdata, size_t N) {
for(size_t i=0; i<N-1; ++i) {
const int swap_idx = Rndom(i, N-1);
if(swap_idx != i) {
const T t = pdata[i];
pdata[i] = pdata[swap_idx];
pdata[swap_idx] = t;
}
}
}
template <typename T, size_t N>
void Shuffle(T (&data)[N]) {
Shuffle(data, N);
}
template <typename T>
void Series(T* pdata, size_t N, T start) {
for(size_t i=0; i<N; ++i) {
pdata[i] = start++;
}
}
template <typename T, size_t N>
void Series(T (&data)[N], T start) {
Series(data, N, start);
}
}
int main() {
using namespace shuffle;
int Data[4]; // I guess you actually want 4
Series(Data, 1); // and maybe to start at 1.
Shuffle(Data); // Shuffle Data's entries.
// Dump Data's entries
for(size_t i=0; i<sizeof(Data)/sizeof(Data[0]); ++i) {
std::cout << Data[i] << ' ';
}
std::cout << '\n';
}
The outputs of 3 executions (over 1 second apart):
2 3 1 4
4 2 3 1
2 4 3 1
Use map or set to store the numbers generated and avoid duplication.
set<int> s;
for (int i = 0;i < 3;i++)
{
int x;
for(;;)
{
int x = Rndom(1, 4) ;
if(s.find(x)==s.end())
{
s.insert(x);
Data[i]=x;
// consider it ..it is not duplicate
break;
}
}
}
Also you can use set or unordered_set to realize the same thing.
The reason of using set over map is std::sets contain only the key, while in std::map there is an associated value.
I'm beginner in programming. Something is giving me trouble to code. Suppose, I've an array.
int Array[] = {3,6,9,5,10,21,3,25,14,12,32,41,3,24,15,26,7,8,11,4};
I want to remove all elements which are greater than 9. How can I do this?
You can do this if you use vector. First initialize vector with your array. Then use remove_if() function. Hope this will help.
#include <algorithm>
#include <vector>
int main()
{
int Array[] = {3,6,9,5,10,21,3,25,14,12,32,41,3,24,15,26,7,8,11,4};
vector<int> V(Array, Array+20);
vector<int> :: iterator it;
it = remove_if(V.begin(), V.end(), bind2nd(greater<int>(), 9));
V.erase (it, V.end()); // This is your required vector if you wish to use vector
}
You cannot remove items from an array, since they are fixed in size.
If you used std::vector, then the solution would look like this:
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
using namespace std;
int main()
{
std::vector<int> Array = {3,6,9,5,10,21,3,25,14,12,32,41,3,24,15,26,7,8,11,4};
Array.erase(remove_if(Array.begin(), Array.end(), [](int n) { return n > 9; }),
Array.end());
copy(Array.begin(), Array.end(), ostream_iterator<int>(cout, " "));
}
Live example: http://ideone.com/UjdJ5h
If you want to stick with your array, but mark the items that are greater than 10, you can use the same algorithm std::remove_if.
#include <algorithm>
#include <iostream>
#include <iterator>
using namespace std;
int main()
{
int Array[] = {3,6,9,5,10,21,3,25,14,12,32,41,3,24,15,26,7,8,11,4};
int *overwrite_start = remove_if(std::begin(Array), std::end(Array), [](int n){ return n>9; });
fill(overwrite_start, std::end(Array), -1);
copy(std::begin(Array), std::end(Array), ostream_iterator<int>(cout, " "));
}
The above will move the "erased" items to the end of the array, and mark them with -1.
Live example: http://ideone.com/7rwaXy
Note the usage in both examples of the STL algorithm functions. The second example with the array uses the same remove_if algorithm function. The remove_if returns the start of the "erased" data, as remove_if doesn't actually remove, but moves the data to the end of the sequence.
i am try swap concept without using vector
int Array[] = {3,6,9,5,10,21,3,25,14,12,32,41,3,24,15,26,7,8,11,4};
int n;
int arr_len = sizeof(Array)/sizeof(int);
void print_array_value() {
int i;
cout << "\n";
for (i = 0; i < arr_len; i++) {
cout << Array[i] << ", ";
}
cout << " : " << arr_len << "\n";
}
void swap_array_value(int start) {
int i;
for ( ; (start+1) < arr_len; start++) {
Array[start] = Array[start+1];
}
}
void remove_array_value() {
int i;
for (i = 0; i < arr_len; i++) {
if (Array[i] > n) {
swap_array_value(i);
arr_len--;
i--;
}
}
}
void main () {
clrscr();
cout << "Enter the N value : ";
cin >> n;
print_array_value();
remove_array_value();
print_array_value();
cout << "Array Length : " << arr_len;
getch();
}