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.
Related
i have an array of 9 numbers and my functions in my number class are used to reorder the 9 numbers in the array without any duplicate of numbers and then to list the number of times the rand() function was called.
I now need to generate ten lists of the numbers and store them into a vector.
here is the code:
class numbers{
private:
int indexCount;
public:
void swap (int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void printArray (int arr[], int n)
{
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << "random calls: " << indexCount <<endl;
}
void randomize (int arr[], int n)
{
indexCount=0;
srand (time(NULL));
for (int i = n - 1; i > 0; i--)
{
int j = rand() % (i + 1);
indexCount++;
swap(&arr[i], &arr[j]);
}
}
};
class numbersVector{
private:
vector <int>numberList;
public:
numbers num;
void storeInVector(int arr[], int n){
for (int i=0; i <10; i++){
num.randomize(arr,n);
num.printArray(arr,n);
numberList.push_back(arr[i]);
}
cout <<endl <<endl;
}
};
int main(){
numbers numbers;
numbersVector nv;
int arr[] = {1, 2, 3, 4, 5, 6, 0, 0, 0};
int n = sizeof(arr) / sizeof(arr[0]);
//numbers.randomize(arr, n);
// numbers.printArray(arr, n);
nv.storeInVector(arr,n);
return 0;
}
in my second class i loop over my functions in the first class to generate 10 list, i am now stuck on storing the randomised list into a vector.
My problem is, i can only store numbers from each list into the vector but i would like to store the 10 lists inside the vector.
EG
for (int i = 0; i <numberList.size(); i++)
{
cout <<numberList[i] <<endl;
}
i would want my output to be:
123456000 random calls: 8
02103654 random calls:8
and so on 10 times.
EDITING POST TO BE MORE CLEAR:
so i have an array
arr[] = {1,2,3,4,5,6,0,0,0}
after my randomise function i get a output like this
{2,1,0,0,6,0,4,3,5}
i then create a loop to run my randomise function 10 times.
ie
1)1,0,0,0,2,5,4,3,6
2)6,0,5,0,4,0,3,2,1
3)5,1,0,0,2,0,3,6,4
....
10)2,1,0,0,6,0,4,3,5
i would then like to store each generated list into a vector
IE
vector <int> numlist;
numList[1] = {1,0,0,0,2,5,4,3,6}
numList[2] = {6,0,5,0,4,0,3,2,1}
and so on
Lists aren't flattened in C++ as they are in some languages (notably perl). You need to specify where you want the elements in your new list inserted and which range you want to insert:
numberList.insert(numberList.end(), std::begin(new_list), std::end(new_list);
This would insert the full range of new_list at the end of your numberList.
Also: As #scohe001 mentioned, use <random> supported functions to get good randomization.
Example:
#include <random>
inline std::mt19937& generator() {
static thread_local std::mt19937 gen(std::random_device{}());
return gen;
}
//...
std::shuffle( numberList.begin(), numberList.end(), generator() );
Example after comments:
#include <algorithm>
#include <iostream>
#include <random>
#include <vector>
inline std::mt19937& generator() {
static thread_local std::mt19937 gen(std::random_device{}());
return gen;
}
int main() {
// a vector of vectors (not the most optimal but for this purpose, good enough)
std::vector<std::vector<int>> result;
std::vector<int> array{1, 2, 3, 4, 5, 6, 7, 8, 9};
for(int i = 0; i < 10; ++i) {
std::shuffle(array.begin(), array.end(), generator());
// pushing back an array (or better, a vector) into the vector
result.push_back(array);
}
//-- present the result
std::cout << result.size() << " random permutations (possibly duplicates):\n";
for(const auto& inner : result) {
for(int value : inner) {
std::cout << value << ' ';
}
std::cout << '\n';
}
}
Demo
If you can't use std::shuffle for some reason, you can make your own by adding a function to generate random numbers and then one to loop over the vector and swap random positions in it.
Example:
// generate a random number in the range [min, max]
template<typename T, std::enable_if_t<std::is_integral_v<T>>* = nullptr>
T my_rand(T min, T max) {
std::uniform_int_distribution<T> dist(min, max);
return dist(generator());
}
// a shuffle-like function
void shake_it(std::vector<int>& c) {
for(size_t i = 0; i < c.size(); ++i) {
std::swap(c[i], c[my_rand(0ul, c.size() - 1)]);
}
}
Then call it with shake_it(array); and it should be properly randomized.
I need my program to make a random sequence from 1-3 each time, but I don't understand how I'd use rand() to make the sequence of numbers 1 to 3 in a different order each program. It can't be the same number again, so I don't know what I'd do to prevent that. An example run would be
123 the first, 231 the second, 321 and so fourth
What would you use to make a sequence that doesn't repeat numbers
The simplest way to generate your sequence would be to use std::shuffle to re-order a vector containing your desired values:
#include <vector>
#include <algorithm>
#include <random>
#include <iostream>
int main()
{
std::random_device rd;
std::mt19937 g(rd());
std::vector<int> elements = { 1, 2, 3 };
std::shuffle(elements.begin(), elements.end(), g);
for (int i : elements)
{
std::cout << i << "\n";
}
}
If you really must use rand() (its not generally a very good random number generator) you can just about squeeze it into shuffle too:
#include <vector>
#include <algorithm>
#include <ctime>
#include <iostream>
struct RandDevice
{
using result_type = uint32_t;
static result_type max() { return static_cast<result_type>(RAND_MAX); };
static result_type min() { return 0; };
result_type operator()() {
return static_cast<result_type>(rand());
}
};
int main()
{
std::vector<int> elements = { 1, 2, 3 };
srand(time(0));
std::shuffle(elements.begin(), elements.end(), RandDevice());
for (int i : elements)
{
std::cout << i << "\n";
}
}
You can use std::next_permutation
Example here : https://en.cppreference.com/w/cpp/algorithm/next_permutation
it's pretty easy to do.. just compare the number you with every occupied element in the array. if it is not in the array, add to array. else, try again.
I have done similar code check this out
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
void displayArray(int randNum[], int elements);
void randomNum(int randNums[], int elements);
int main ()
{
//declare array
int numbers[999] = {0};
//random number generator
srand(static_cast<int>(time(0)));
randomNum(numbers, 999);
displayArray(numbers, 999);
system("pause");
return 0;
}
void randomNum(int randNums[], int elements)
{
for (int i = 0; i < elements; i++)
{
bool same;
do
{
same = false;
randNums[i] = rand() % 999 + 100;
// Check if the newly generated number is a duplicate:
for (int check = 0; check < i; check++)
{
if (randNums[i] == randNums[check])
{
same = true;
break;
}
}
} while (same);
}
}
void displayArray(int randNum[], int elements)
{
for (int sub = 0; sub < elements; sub ++)
{
cout << "Unique Numbers: " << randNum[sub] << endl;
}
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I have ant task, to search most frequent odd number in vector array. I cant figure it out.
this is, how i am writing data, to array
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
class oddNum {
private:
vector <int> numbers;
int number, n;
public:
void getData() {
cin >> n;
for (int i = 0; i < n; ++i) {
cin >> number;
if(number % 2 != 0) {
numbers.push_back(number);
}
}
}
};
int main() {
oddNum n;
n.getData();
return 0;
}
my numbers
8 5 5 1 3
There are several ways to do it, I show you two. The first one is not intuitive and requires quite the bookmarking. However, the last solution uses the modern containers and their nature to do this in an elegant style.
First you sort the vector. This way all equal elements are next to each other. Than you iterate through this vector to look for the largest pack of elements while skipping all even numbers. Create a variable counter which resets if the elements change (this can be done by comparing the current element to the next element of the array) and a max variable that holds the largest value of said counter. Whenever this counter exceeds the value of max you have found the most common element so far which can be saved in a variable result. When you're done iterating, the variable result will contain the most frequent odd element of the vector. This implementation, in addition to <vector>, also needs the <algorithm> and <cassert> headers.
int get_most_frequent_odd(const std::vector<int>& vec) {
assert(!vec.empty());
std::vector<int> sorted = vec;
std::sort(sorted.begin(), sorted.end());
unsigned counter = 0u;
unsigned max = 0u;
int result;
for (unsigned i = 0u; i < sorted.size() - 1; ++i) {
if (sorted[i] % 2 != 0) {
if (sorted[i] == sorted[i + 1]) {
++counter;
if (max < counter) {
max = counter;
counter = 0u;
result = sorted[i];
}
}
else {
counter = 0u;
}
}
}
return result;
}
The function is quite specific (only for int's and odd elements). Also your getData() function already sorts out all even numbers. So here's a more generic function get_most_frequent<T>:
template<typename T>
T get_most_frequent(const std::vector<T>& vec) {
assert(!vec.empty());
std::vector<T> sorted = vec;
std::sort(sorted.begin(), sorted.end());
unsigned counter = 0u;
unsigned max = 0u;
T result;
for (unsigned i = 0u; i < sorted.size() - 1; ++i){
if (sorted[i] == sorted[i + 1]) {
++counter;
if (max < counter) {
max = counter;
counter = 0u;
result = sorted[i];
}
}
else {
counter = 0u;
}
}
return result;
}
Now a std::unordered_map or std::map will be superior over a std::vector for this task as they are build in a way that allows you to skip this ugly bookmarking. It's way more readable, too. But given you said you are a beginner I didn't put this at first place. The idea is to count the frequency by using a std::unordered_map. The elements are set to be the keys of the map and incrementing the values behind the keys will give you the occurrency of the elements. (Thanks #YSC) You can now use std::max_element which will return the pair with the highest saved occurrence. This implementation requires the <unordered_map>, <utility>, <algorithm> and <cassert> headers.
template<typename T>
T get_most_frequent(const std::vector<T>& vec) {
std::unordered_map<T, int> frequency_map;
for (auto i : vec) {
++frequency_map[i];
}
return std::max_element(frequency_map.begin(), frequency_map.end())->first;
}
example run using either of these 3 functions:
how many numbers?: 8
input number 1: 5
input number 2: 5
input number 3: 4
input number 4: 9
input number 5: 9
input number 6: 9
input number 7: 11
input number 8: 0
most common element is: 9
full code:
#include <iostream>
#include <unordered_map>
#include <vector>
#include <algorithm>
#include <cassert>
template<typename T>
T get_most_frequent(const std::vector<T>& vec) {
std::unordered_map<T, int> frequency_map;
for (auto i : vec) {
++frequency_map[i];
}
return std::max_element(frequency_map.begin(), frequency_map.end())->first;
}
class oddNum {
private:
std::vector<int> numbers;
public:
void getData() {
std::size_t size;
std::cout << "how many numbers?: ";
std::cin >> size;
int number;
for (int i = 0; i < size; ++i) {
std::cout << "input number " << i + 1 << ": ";
std::cin >> number;
if (number % 2 != 0) {
numbers.push_back(number);
}
}
std::cout << "most common element is: " << get_most_frequent(numbers) << '\n';
}
};
int main() {
oddNum n;
n.getData();
}
I have created a simple mode calculator and I am displaying random list - something like this:
12 14 11 10 15 13 16 13 14 14 11 13 16 15 15 15 10 14 13 14 12 13 14 12
The mode value is 6
The mode is 14
. But my problem is I can't get the pair list to show instead of showing the list way - I want to display it this as a item-count pair list :
{2,3}, {4,3}, {5,2}, {3,2}, {1,2}
and the modes are clearly 2 and 4.
can anyone help me solve this issue? thanks for the help.
Here is an image for more details: https://imgur.com/a/FYNcxkv
here is my code:
#include <ctime>
#include <iomanip>
#include <iostream>
#include <string>
#include <random>
using namespace std;
default_random_engine e(static_cast<unsigned>(time(NULL)));
void fill(int a[], int size, int value)
{
for(int i = 0; i < size; i++)
a[i] = value;
}
void randomFill(int a[], int size, int lb, int up)
{
uniform_int_distribution<int> u(lb, up);
for(int i = 0; i < size; i++)
a[i] = u(e);
}
void show(int a1d[], int size)
{
for(int i = 0; i < size; i++)
cout << setw(2) << a1d[i] << ' ';
cout << endl;
}
int count(int a1d[], int size, int value)
{
int vcount = 0;
for(int i = 0; i < size; i++)
if(a1d[i] == value) vcount++;
return vcount;
}
int findLargest(int a1d[], int size)
{
int largest = a1d[0];
for(int i = 1; i < size; i++)
if(a1d[i] > largest) largest = a1d[i];
return largest;
}
/*
the mode of a set of things is that thing that appears the greater number of times in the set
a set may have several modes
*/
int computemodes(int source[], int size, int modes[], int& msize)
{
/*
1. fill the modes array with zeroes
*/
fill(modes, size, 0);
/*
2. store the number of times each source element appears in the modes array.
if an element appears more than once in the source array then its counts appears
more than once the modes array.
source and modes form a parallel array structure
*/
for(int i = 0; i < size; i++)
modes[i] = count(source, size, source[i]);
/*
3. calculate the largest number in the modes array. this number is the number of
times the mode or modes appears in the source array
*/
int modevalue = findLargest(modes, size);
/*
4. assign -1 to the mode array elements that are less than the mode value
now only mode values in the modes array are not equal to -1.
the corresponding elements in the source array are the modes.
*/
for(int i = 0; i < size; i++)
if(modes[i] != modevalue) modes[i] = -1;
/*
5. we use the modes array to identify the source elements that are modes:
any element in the modes array that is not -1 corresponds to a mode in the
source array. if the mode is 1 then every source element is a mode
and no element in the modes array is -1; if the mode is greater than 1 then
a. many modes array entries are -1
b. the number of times a mode appears in the source equals its corresponding modes value
c. the number of modes array entries that are not -1 are the number of times the modes
appear in the source array
the following nested for loop transforms the modes array into an array in which
the first appearance of a mode in the source corresponds to a modes array entry
that is not -1 and subsequent appearances of this mode in the source correspond to
modes array entries that are -1.
*/
for(int i = 0; i < size; i++)
if(modes[i] != -1) //first appearance of the mode in the source
for(int j = i + 1; j < size; j++)
if(source[i] == source[j]) modes[j] = -1;
//subsequent appearances
/*
at this point the usage of the modes array changes.
heretofore, an entry that is not -1 in the modes array is the number of times
a mode appears in the source array. now an entry in the modes array is a mode.
the loop adds modes from the source array to the modes array.
msize serves 2 purposes:
a. it is number of modes copied so far.
b. it is the next free modes array position.
*/
msize = 0;
for (int i = 0; i < size; i++)
if (modes[i] != -1) //first occurrence of a mode in the source
{
modes[msize] = source[i];
msize++;
}
return modevalue;
}
int main()
{
const int size = 24;
int a[size];
int m[size];
randomFill(a, size, 10, 16);
show(a, size);
int msize = 0;
int modevalue = computemodes(a, size, m, msize);
cout << "The mode value is " << modevalue << endl;
if (msize == 1)
cout << "The mode is ";
else
cout << "The modes are ";
show(m, msize);
system("pause");
return 0;
}
You can create your map count with:
template <typename T>
std::map<T, std::size_t> map_count(const std::vector<T>& v)
{
std::map<T, std::size_t> res;
for (const auto& e: v) { res[e]++; }
return res;
}
and from that:
template <typename T>
std::pair<const T, std::size_t> find_mode(const std::map<T, std::size_t>& m)
{
if (m.empty()) {throw std::runtime_error("empty map");}
return *std::max_element(m.begin(),
m.end(),
[](const auto& lhs, const auto& rhs){ return lhs.second < rhs.second; }
);
}
Demo
I would design your code problem something like this:
#include <iostream>
#include <string>
#include <random>
#include <vector>
#include <map>
#include <algorithm> // could be used in your calculate function - algorithm
#include <numeric> // same as above.
class ModeCaclulator {
private:
std::vector<int> generatedNumbers_;
int highestModeCount_;
int highestModeValue;
typedef std::map<int,int> Modes;
Modes allModeCounts_;
public:
ModeCalculator() = default; // default constructor
template<typename T = int> // variadic constructor
ModeCalculator( T&&... t ) : generatedNumbers_{ t... } {
calculateModes();
}
std::vector<int>& getAllNumbers() const { return generatedNumbers_; }
int getHighestModeCount() const { return getHighestModeCount_; }
int getHighestModeValue() const { return getHighestModeValue_; }
Modes getAllModes() const { return allModeCounts_; }
void generateNumbers(int count, int lower, int upper) {
std::random_device rd;
std::mt19937 gen( rd() );
std::uniform_int_distribution<> dis( lower, upper );
for ( int i = 0; i < count; i++ )
generateNumbers_.push_back( dis( gen ) );
}
void calculateModes() {
// This is where you would perform your algorithm
// After doing the proper calculations this is where you would
// save the highestModeValue_ & highestModeCount_ as well as
// populating the vector of maps member.
// In this function you can use local lambdas to find the highest mode count and value.
}
void displayModeInformation() const {
std::cout << Random Values: << '\n';
for ( auto& v : generatedNumbers )
std::cout << v << " ";
std::cout << '\n'
std::cout << "Highest Mode Count: " << highestModeCount_ << '\n';
std::cout << "Highest Mode Value: " << highestModeValue_ << '\n';
std::cout << "\n"
std::cout << "All Mode Count & Value Pairs:\n";
for ( auto& p : allModeCounts_ ) {
std::cout << "{" << p.first << "," << p.second << "}" << " "
}
std::cout << '\n';
}
};
int main() {
ModeCalculator mc;
mc.generateNumbers( 15, 1, 16 );
mc.calculateModes();
mc.displayModeInformation();
// If using variadic constructor
ModeCalculate mc2( 12, 15, 14, 19, 18, 12, 15, 19, 21, 12, 18, 19, 21, 14 );
// no need to call calculateModes() this constructor does that for u
mc2.displayModeInformation();
return 0;
}
This makes the code much more readable, and look how clean main is, and all of the functionality is encapsulated into a single class instead of a handful of floating functions... Internal data is protected or hidden and can only be retrieved through accessor functions. The use of stl containers provides a clean interface instead of the use of C style arrays and also helps to prevent the use of raw pointers, and dynamic memory - via new & delete or new[] & delete[]. It also allows the code to be easier to manage and to debug, and provides a user with a generic reusability.
This is for a class so please don't be too specific, but I am looking for a way to list all permutations of an array of digits.
We have to arrange different numbers on different pillars (like a lock) to unlock a combination. There may be 6 numbers on each of the 4 pillars. But it should work for any n on r as long as n>r.
I have the way to randomly generate a combination, and methodically look for it in a list but I am having trouble producing an algorithm to generate all permutations.
I am able to get all combinations for digits 1-6 using this in C++:
//n = number of digits - 1; list = list of digits to work with;
//number=finalized list of digits
void permute(int n, vector<int> list, vector<vector<int>>* number)
{
if(n==1)
{
number->push_back(list);
}else
{
for(int i = 1;i<n;i++)
{
permute(n-1,list, number);
if(n%2 == 0)
{
swap(list[1],list[n]);
}else
{
swap(list[i],list[n]);
}
}
}
};
But then i get a list such as
123456
163452
etc where 1 is always the first digit
but I need to also obtain when the first digit is switched around and only 4 digits are present.
example
6341
4163
etc where there are 4 digits that range from 1-6 and you have all possible combinations.
Can anyone point me in the right direction for another algorithm to supplement this or so?
C++ offers a perfect solution for this - it's std::next_permutation (you need to include <algorithms> to use it).
vector<int> list;
std::sort(list.begin(), list.end());
do {
// use the current permutation of the list
} while (std::next_permutation(list.begin(), list.end()));
An important point to remember about this function is that if you would like to go through all permutations of a range, the range must be sorted before you make the first call to next_permuration, otherwise you are going to stop before exhausting all permutations.
If you need to implement your own, this may be no help, but C++ has next_permutation built-in.
http://www.cplusplus.com/reference/algorithm/next_permutation/
The algorithm behind this function is explained here: std::next_permutation Implementation Explanation
A general algorithm for recursively generating permutations of N-length from a list of N items is:
For each element x in list
Make a copy of list without element x; call it newList
Find all of the permutations of newList (thats the recursion, btw)
Add element x to the beginning of each permutation of newList
#include <iostream>
#include <list>
typedef std::list<int> IntList;
void iterlist(IntList& lst)
{
for (IntList::iterator it=lst.begin(); it!=lst.end(); it++)
cout << " " << *it;
cout << endl;
}
std::list<IntList> permute(IntList& L1)
{
if (L1.size() == 1)
return std::list<IntList>(1,L1);
std::list<IntList> res;
for (IntList::iterator i = L1.begin(); i != L1.end();)
{
// remember this
int x = (*i);
// make a list without the current element
IntList tmp(L1.begin(), i++);
tmp.insert(tmp.end(), i, L1.end());
// recurse to get all sub-permutations
std::list<IntList> sub = permute(tmp);
// amend sub-permutations by adding the element
for (std::list<IntList>::iterator j=sub.begin(); j!=sub.end();j++)
(*j).push_front(x);
// finally append modified results to our running collection.
res.insert(res.begin(), sub.begin(), sub.end());
}
return res;
}
int main()
{
IntList lst;
for (int i=0;i<4;i++)
lst.push_back(i);
std::list<IntList> res = permute(lst);
for (std::list<IntList>::iterator i=res.begin(); i!=res.end(); i++)
iterlist(*i);
return 0;
}
First of All, let's talk your question to print all the P(6,4) array in set {1,2,3,4,5,6}, but std::next_permutation will only adapt for the permutation of all the element (P(6,6)), not suitable for your issue (P(6,4)).
I think use std::next_permutation can get the combination very easily, and since we know P(6,4)=C(6,4)*P(4,4), the simple code implementation maybe like this:
1 #include <iostream>
2 #include <vector>
3
4 int main()
5 {
6 std::vector<int> list;
7 std::vector<int> subList;
8 std::vector<bool> flag;
9
10 for (int i=1; i<=6; ++i)
11 list.push_back(i);
12 flag.insert(flag.end(),4,1);
13 flag.insert(flag.end(),2,0);
14 std::sort(flag.begin(), flag.end());
15 do
16 {
17 subList.clear();
18 for(int i=0; i<flag.size(); ++i)
19 {
20 if(flag[i])
21 {
22 subList.push_back(list[i]);
23 }
24 }
25 do
26 {
27 for(std::vector<int>::iterator it=subList.begin(); it!=subList.end(); ++it)
28 {
29 std::cout << *it << " ";
30 }
31 std::cout << std::endl;
32 }while(std::next_permutation(subList.begin(), subList.end()));
33 std::cout << std::endl;
34 } while(std::next_permutation(flag.begin(), flag.end()));
35 return 0;
36 }
That's obviously the out loop look for C(6,4), and the inner loop look for P(4,4).
Didn't take much time on your code, for combination, you can use search method just like DFS, refer: combinations of
This function lists all permutations using bitset
#include <iostream>
#include <string>
#include <bitset>
using namespace std;
const int N = 3;
void permute(string_view s, bitset<N> &mask, string &pref)
{
if (mask.all()) {
cout << pref << endl;
return;
}
for (int i = 0; i < N; i++) {
if (!mask[i]) {
mask.set(i);
pref.push_back(s[i]);
permute(s, mask, pref);
pref.pop_back();
mask.reset(i);
}
}
}
int main()
{
string pref;
bitset<N> mask;
permute(string("abc"), mask, pref);
return 0;
}
and with a few modifications, it prints all combinations
#include <iostream>
#include <string>
#include <bitset>
using namespace std;
const int N = 3;
const int M = 2;
void permute(string_view s, bitset<N> &mask, string &pref)
{
if (pref.size() == M) {
cout << pref << endl;
return;
}
for (int i = 0; i < N; i++) {
if (!mask[i]) {
mask.set(i);
permute(s, mask, pref);
pref.push_back(s[i]);
permute(s, mask, pref);
pref.pop_back();
mask.reset(i);
break;
}
}
}
int main()
{
string pref;
bitset<N> mask;
permute(string("abc"), mask, pref);
return 0;
}