I need a different version of permutations for my code. I could able to achieve what I want but it is not generic enough. my algorithm keeps going bigger along with my requirements. But that should not be.
This is not a home work for any one, I need it for one my critical projects, wondering if any pre-defined algorithms available from boost or any other.
Below is the standard version of next_permutation using c++.
// next_permutation example
#include <iostream> // std::cout
#include <algorithm> // std::next_permutation
int main ()
{
int myints[] = {1,2,3};
do
{
std::cout << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n';
} while ( std::next_permutation(myints,myints+3) );
return 0;
}
That gives below output :
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
But my requirement is :- Let's say I have 1 to 9 numbers :
1,2,3,4,5,6,7,8,9
And I need a variable length of permutations and in only ASCENDING order and with out DUPLICATES.
Let's say i need 3 digit length of permutations then i need output as below.
123
124
125
.
.
.
128
129
134 // After 129 next one should be exactly 134
135 // ascending order mandatory
136
.
.
.
148
149
156 // exactly 156 after 149, ascending order mandatory
.
.
.
489 // exactly 567 after 489, because after 3rd digit 9, 2nd digit
567 // will be increased to 49? , so there is no possibility for
. // 3rd digit, so first digit gets incremented to 5 then 6 then
. // 7, in ascending order.
.
.
.
789 // and this should be the last set I need.
My list may contain upto couple of hundred's of numbers and variable length can be 1 to up to Size of the list.
My own algorithm is working for specific variable length, and a specific size, when they both changes, i need to write huge code. so, looking for a generic one.
I am not even sure if this is called as Permutations or there is a different name available for this kind of math/logic.
Thanks in advance.
musk's
Formally, you want to generate all m-combinations of the set [0;n-1].
#include <iostream>
#include <vector>
bool first_combination (std::vector<int> &v, int m, int n)
{
if ((m < 0) || (m > n)) {
return false;
}
v.clear ();
v.resize (m);
for (int i = 0; i < m; i++) {
v[i] = i;
}
return true;
}
bool next_combination (std::vector<int> &v, int m, int n)
{
for (int i = m - 1; i >= 0; i--) {
if (v[i] + m - i < n) {
v[i]++;
for (int j = i + 1; j < m; j++) {
v[j] = v[j - 1] + 1;
}
return true;
}
}
return false;
}
void print_combination (const std::vector<int> &v)
{
for (size_t i = 0; i < v.size(); i++) {
std::cout << v[i] << ' ';
}
std::cout << '\n';
}
int main ()
{
const int m = 3;
const int n = 5;
std::vector<int> v;
if (first_combination (v, m, n)) {
do {
print_combination (v);
} while (next_combination (v, m, n));
}
}
You can use this code and the linked article as inspiration.
This task can be done with a simple iterative algorithm. Just increment the first element that can be incremented and rescale the elements before it until there is no element to be incremented.
int a[] = {0,1,2,3,4,5,6,7,8,9}; // elements: must be ascending in this case
int n = sizeof(a)/sizeof(int);
int digits = 7; // number of elements you want to choose
vector<int> indexes; // creating the first combination
for ( int i=digits-1;i>=0;--i ){
indexes.push_back(i);
}
while (1){
/// printing the current combination
for ( int i=indexes.size()-1;i>=0;--i ){
cout << a[indexes[i]] ;
} cout << endl;
///
int i = 0;
while ( i < indexes.size() && indexes[i] == n-1-i ) // finding the first element
++i; // that can be incremented
if ( i==indexes.size() ) // if no element can be incremented, we are done
break;
indexes[i]++; // increment the first element
for ( int j=0;j<i;++j ){ // rescale elements before it to first combination
indexes[j] = indexes[i]+(i-j);
}
}
Output:
0123456
0123457
0123458
0123459
0123467
0123468
0123469
0123478
0123479
0123489
0123567
0123568
0123569
0123578
0123579
0123589
0123678
0123679
0123689
0123789
0124567
0124568
0124569
0124578
0124579
0124589
0124678
0124679
0124689
0124789
0125678
0125679
0125689
0125789
0126789
0134567
0134568
0134569
0134578
0134579
0134589
0134678
0134679
0134689
0134789
0135678
0135679
0135689
0135789
0136789
0145678
0145679
0145689
0145789
0146789
0156789
0234567
0234568
0234569
0234578
0234579
0234589
0234678
0234679
0234689
0234789
0235678
0235679
0235689
0235789
0236789
0245678
0245679
0245689
0245789
0246789
0256789
0345678
0345679
0345689
0345789
0346789
0356789
0456789
1234567
1234568
1234569
1234578
1234579
1234589
1234678
1234679
1234689
1234789
1235678
1235679
1235689
1235789
1236789
1245678
1245679
1245689
1245789
1246789
1256789
1345678
1345679
1345689
1345789
1346789
1356789
1456789
2345678
2345679
2345689
2345789
2346789
2356789
2456789
3456789
Related
Elements : a b c
all combinations in such a way:abcabacbcabc
Formula to get total number of combinations of unique elements without repetition = 2^n - 1 (where n is the number of unique elements)
In our case top: 2^3 - 1 = 7
Another formula to get the combinations with specific length = n!/(r! * (n - r)!) (where n= nb of unique items and r=length)
Example for our the above case with r=2 : 3!/(2! * 1!) = 3 which is ab ac bc
Is there any algorithm or function that gets all of the 7 combinations?
I searched a lot but all i can find is one that gets the combinations with specific length only.
UPDATE:
This is what I have so far but it only gets combination with specific length:
void recur(string arr[], string out, int i, int n, int k, bool &flag)
{
flag = 1;
// invalid input
if (k > n)
return;
// base case: combination size is k
if (k == 0) {
flag = 0;
cout << out << endl;
return;
}
// start from next index till last index
for (int j = i; j < n; j++)
{
recur(arr, out + " " + arr[j], j + 1, n, k - 1,flag);
}
}
The best algorithm I've ever find to resolve this problem is to use bitwise operator. You simply need to start counting in binary. 1's in binary number means that you have to show number.
e.g.
in case of string "abc"
number , binary , string
1 , 001 , c
2 , 010 , b
3 , 011 , bc
4 , 100 , a
5 , 101 , ac
6 , 110 , ab
7 , 111 , abc
This is the best solution I've ever find. you can do it simply with loop. there will not be any memory issue.
here is the code
#include <iostream>
#include <string>
#include <math.h>
#include<stdio.h>
#include <cmath>
using namespace std;
int main()
{
string s("abcd");
int condition = pow(2, s.size());
for( int i = 1 ; i < condition ; i++){
int temp = i;
for(int j = 0 ; j < s.size() ; j++){
if (temp & 1){ // this condition will always give you the most right bit of temp.
cout << s[j];
}
temp = temp >> 1; //this statement shifts temp to the right by 1 bit.
}
cout<<endl;
}
return 0;
}
Do a simple exhaustive search.
#include <iostream>
#include <string>
using namespace std;
void exhaustiveSearch(const string& s, int i, string t = "")
{
if (i == s.size())
cout << t << endl;
else
{
exhaustiveSearch(s, i + 1, t);
exhaustiveSearch(s, i + 1, t + s[i]);
}
}
int main()
{
string s("abc");
exhaustiveSearch(s, 0);
}
Complexity: O(2^n)
Here's an answer using recursion, which will take any number of elements as strings:
#include <vector>
#include <string>
#include <iostream>
void make_combos(const std::string& start,
const std::vector<std::string>& input,
std::vector<std::string>& output)
{
for(size_t i = 0; i < input.size(); ++i)
{
auto new_string = start + input[i];
output.push_back(new_string);
if (i + 1 == input.size()) break;
std::vector<std::string> new_input(input.begin() + 1 + i, input.end());
make_combos(new_string, new_input, output);
}
}
Now you can do:
int main()
{
std::string s {};
std::vector<std::string> output {};
std::vector<std::string> input {"a", "b", "c"};
make_combos(s, input, output);
for(auto i : output) std::cout << i << std::endl;
std::cout << "There are " << output.size()
<< " unique combinations for this input." << std::endl;
return 0;
}
This outputs:
a
ab
abc
ac
b
bc
c
There are 7 unique combinations for this input.
Recently I have been trying to do a problem that requires me to find all the different combinations with selecting only 1 element from each row. For example, I'm inputting n rows with 2 strings per row. However, I only want to find all the different combinations where I choose 1 string from each row.
Example:
Input:
3
alex bob
straw mat
eat drink
Example combination:
alex straw drink
This results in 2^n combinations, which in this case would be 2^3 = 8 combinations. However, if I was to use n for loops to find the combinations
e.g.
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int n;
int main(int argc, char ** argv) {
cin >> n; //rows of words
string words[n][2]; //the words with 2 words per row
for (int i = 0; i < n; i++) {
for (int j = 0; j < 2; j++) {
cin >> words[i][j]; //input of words
}
}
//finding all possible combinations
for (int i =0; i<n; i++){
for (int j=0; j<2; j++){
for (int x=0; x<2; x++){
//and so on per n
}
}
}
return 0;
}
this would take n for loops to find out all the combinations of the array with only taking one item from each row. What would be the best and simplest approach to finding all different combinations with size n as I would take 1 string out of the two in each row? Thanks.
You can do recursion.
Assuming C++11, something like this maybe (didn't try to compile this though):
// finding all possible combinations
std::vector<std::vector<std::string>> combinations;
const auto processLine = [&](const std::vector<std::string>& currentCombination, int line) {
std::vector<std::string> combination0 = currentCombination;
std::vector<std::string> combination1 = currentCombination;
combination0.push_back(words[line][0]);
combination1.push_back(words[line][1]);
if (line + 1 < n) {
// process next line
processLine(combination0, line + 1);
processLine(combination1, line + 1);
}
else {
// last line - keep the result
combinations.push_back(combination0);
combinations.push_back(combination1);
}
};
std::vector<std::string> empty;
processLine(empty, 0);
// print results
for (const auto& combination : combinations) {
for (const auto& word : combination) {
std::cout << word << " ";
}
std::cout << std::endl;
}
A very simple solution for a setting where you have always 2 elements per row would be to use datatype integer and interpret each bit as a decision for the first or the second column in the respective row; then simply count from 0 to 2^n - 1 in order to get all combinations.
Applied to your example this would look as follows:
int bits meaning
0 000 alex,straw,eat
1 001 alex,straw,drink
2 010 alex,mat,eat
3 011 alex,mat,dring
4 100 bob,straw,eat
5 101 bob,straw,drink
6 110 bob,mat,eat
7 111 bob,mat,drink
For any of the given integer values 0..7, use bit shift operators or &-bitmask to map each bit to a column index:
void getCombinationRepresentedByIntValue(vector<string>& combination, int value) {
int mask = 1;
for (int i=n-1; i>=0; i--) {
if (value & mask)
combination.push_back(words[i][1]);
else
combination.push_back(words[i][0]);
mask = mask << 1;
}
}
That seems to answer your question :
int ct[n]; // count of the number of pass
int current = 0; // index of the current word (n)
/* while not all combinaison have been exploited */
while (current >= 0)
{
cout << words[current][ct[current]]; /* <<<<< can be used another way*/
/* down to the next word */
current ++; // to get the next word
if (current >=n) { // at the end of the list
cout << " ";
current--; // restore last
ct[current]++; // increment number of time we passed
/* find the previous not completely exploited */
while (current >= 0 && ct[current]> 1) /* <<< change 1 to any number of words per line */
{
ct[current] = 0;
current--;
if (current >= 0) ct[current]++;
}
if (current > 0 ) current = 0;
}
}
With your example :
Input :
3
alex bob
straw mat
eat drink
output :
alexstraweat
alexstrawdrink
alexmateat
alexmatdrink
bobstraweat
bobstrawdrink
bobmateat
bobmatdrink
hope it helps !
I can't figure out the logic behind this one... here's what I have so far:
#include <iostream>
using namespace std;
int thearray[4][4];
int NbPos = 4;
int main() {
int i2;
int q2;
for(int i = 1; i < 4; i++) {
for(int q = 1; q < 4; q++) {
for(int c = 0; c < NbPos; c++) {
thearray[i][q] = c;
}
}
}
}
This is filling the array up to the end is still:
3 3 3
3 3 3
3 3 3
but it's doing so without hitting anywhere near every possible combination.
Ideally once it gets to:
0 0 0
0 0 0
0 0 3
the next step SHOULD be:
0 0 0
0 0 0
0 1 0
so it hits a TON of combinations. Any ideas on how to make it hit them all? I'm stumped on the logic!
with the way you're iterating over this, a 1-dimensional array would make the looping simpler. you can still mentally treat it to have rows and columns, however they are just layed out end-to-end in the code.
you could try something like this; however if you want it in a 2D format specifically that challenge is left to you ;)
#include <iostream>
using namespace std;
#define rows 4
#define columns 4
int main() {
int thearray[rows * columns] = {0};
int NbPos = 4;
int lastPos = rows * columns - 1;
while (true) {
thearray[lastPos]++;
int pos = lastPos;
while (thearray[pos] == NbPos and pos >= 1) {
thearray[pos - 1]++;
thearray[pos] = 0;
pos--;
}
bool finished = true;
for (int i = 0; i < rows * columns; i++) {
if (thearray[i] != NbPos - 1) {
finished = false;
}
}
if (finished) {
break;
}
}
for (int i = 0; i < rows * columns; i++) {
std::cout << thearray[i] << " ";
if (i % rows == rows - 1) {
cout << endl; // makes it look like a 2D array
}
}
}
It makes sense to have the final form as all 3s , since you loop every element of the array and you assign it at the end with 3 .
So the next element will only take into account the combination with the final value of the previous element (which will be 3).
Thinking in math terms, your complexity is N^3 so to speak (actually is N^2 * 4 , but since your N is 3 ...).
Your approach is wrong, since you want to find permutations, which are defined by a factorial function , not a polinomial function.
The necessary complexity for the output doesn't match the complexity of your algorithm (your algorithm is incredbily fast for the amount of output needed).
What you are looking for is backtracking (backtacking will match the complexity needed for your output).
The recursion function should be something like this (thinking on a 1D array, with 9 elements):
RecursiveGeneratePermutations(int* curArray, int curIdx)
{
if (curIDX==9)
{
for (int i=0; i<9;i++)
{
// write the array
}
} else {
curArray[curIdx]=0;
RecursiveGeneratePermutations(curIdx+1);
curArray[curIdx]=1;
RecursiveGeneratePermutations(curIdx+1);
curArray[curIdx]=2;
RecursiveGeneratePermutations(curIdx+1);
curArray[curIdx]=3;
RecursiveGeneratePermutations(curIdx+1);
}
}
Now you only need to call the function for the index 0 :
RecursiveGeneratePermutations(arrayPtr,0);
Then wait...allot :).
I have a vector of integers. For example: 26 58 32 47 . I need to replace them with their number in that sequence. In this case it would be: 4 1 3 2 . I tried this code:
int n = 1;
vector <int> vietos;
for (vector <int>::iterator i = vieta.begin(); i != vieta.end(); i++) {
for (vector <int>::iterator j = vieta.begin(); j != vieta.end(); j++) {
if (*i > *j)
n++;
}
vietos.push_back(n);
cout << n << " ";
n = 1;
}
Having numbers 23 25 38 28 26 28 (Note: In this case I number them in reverse order!) I get: 1 2 6 4 3 4 which is good except for two numbers are equal.
Maybe there is some way to number elements in vector using STL algorithms?
In my opinion the simplest way is to use std::reference_wrapper. The code will look simple and very clear.
Here is the program that demonstrates the approach.
Enjoy!:)
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
int main()
{
std::vector<int> v = { 23, 25, 38, 28, 26, 28 };
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
// Introducing a local block scope that the auxiliary vector would be automatically deleted
{
std::vector<std::reference_wrapper<int>> vr( v.begin(), v.end() );
std::stable_sort( vr.begin(), vr.end() );
for ( std::vector<std::reference_wrapper<int>>::size_type i = 0;
i < vr.size();
i++ )
{
vr[i].get() = i + 1;
}
}
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
return 0;
}
The output is
23 25 38 28 26 28
1 2 6 4 3 5
If you need to get the reverese order all you need is to add to the code functional object
std::greater<std::reference_wrapper<int>>()
in the call of std::stable_sort
For example
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
int main()
{
std::vector<int> v = { 23, 25, 38, 28, 26, 28 };
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
// Introducing a local block scope that the auxiliary vector would be automatically deleted
{
std::vector<std::reference_wrapper<int>> vr( v.begin(), v.end() );
std::stable_sort( vr.begin(), vr.end(),
std::greater<std::reference_wrapper<int>>() );
for ( std::vector<std::reference_wrapper<int>>::size_type i = 0;
i < vr.size();
i++ )
{
vr[i].get() = i + 1;
}
}
for ( int x : v ) std::cout << x << ' ';
std::cout << std::endl;
return 0;
}
The output is
23 25 38 28 26 28
6 5 1 2 4 3
Is not it the best solution is it? :)
EDIT: Maybe there is no sense to use std::stable_sort with the functional object. It will be enough to use for loop setting numbers in the reverse order. Something as
for ( std::vector<std::reference_wrapper<int>>::size_type i = 0;
i < vr.size();
i++ )
{
vr[vr.size() + i - 1].get() = i + 1;
}
In that case, you should increment when the value is greater than or equal to rather than just greater than, try this:
(*i >= *j)
If you were to replace the iterators with integers, i.e.: (I assume < isn't defined on iterators, but it could be)
for (int i = 0; i < vietos.size(); i++)
You could increment n as well when elements to the left are equal, i.e. when
vietos[i] > vietos[j] || (vietos[i] == vietos[j] && j < i).
Alternatively, you could create a vector<pair<int, int> >, with each pair containing the element and its index, then sort that, and iterate through the sorted vector, setting the index in the pair in the original vector to the index in the sorted vector.
This would give an O(n log n) running time, as opposed to the O(n²) of the above.
Pseudo-code:
vector arr
vector<pair> pairs
for i = 0 to n
pairs.insert(arr[i], i)
sort pairs
for i = 0 to n
arr[pairs[i].second] = i
I have 3-column integer arrays, whose last 2 elements are for sorting. For example
10 0 1
11 0 2
12 1 2
13 0 1
I want them to become:
10 0 1
13 0 1
11 0 2
12 1 2
The arrays are first sorted according to the 2nd column, and then again according to 3rd column.
I have over 3000 rows, so I need something also fast. How can you do this in c++?
Note: The array will be allocated dynamically using the following templates:
template <typename T>
T **AllocateDynamic2DArray(int nRows, int nCols){
T **dynamicArray;
dynamicArray = new T*[nRows];
for( int i = 0 ; i < nRows ; i++ ){
dynamicArray[i] = new T[nCols];
for ( int j=0; j<nCols;j++){
dynamicArray[i][j]= 0;
}
}
return dynamicArray;
}
in main,
int ** lineFilter = AllocateDynamic2DArray(2*numberOfLines,3);
you can use std::sort(); however, this is complicated by your array being 2D.
In general, std::sort() can't eat 2D arrays; you have to create a class to cast around the compiler warnings and complaints:
#include <iostream>
#include <algorithm>
int data[4][3] = {
{10,0,1},
{11,0,2},
{12,1,2},
{13,0,1}
};
struct row_t { // our type alias for sorting; we know this is compatible with the rows in data
int data[3];
bool operator<(const row_t& rhs) const {
return (data[1]<rhs.data[1]) || ((data[1]==rhs.data[1]) && (data[2]<rhs.data[2]));
}
};
int main() {
std::sort((row_t*)data,(row_t*)(data+4));
for(int i=0; i<4; i++)
std::cout << i << '=' << data[i][0] << ',' << data[i][1] << ',' << data[i][2] << ';' << std::endl;
return 0;
}
It becomes much easier if you use a std::vector to hold your items that really are of type row_t or such. Vectors are dynamically sized and sortable.
I think this should work:
template<typename T>
struct compareRows {
bool operator() (T * const & a, T * const & b) {
if (a[1] == b[1])
return a[2] < b[2];
else
return a[1] < b[1];
}
};
std::sort(dynamicArray, dynamicArray+nrows, compareRows<int>());
Use a functor to implement the comparison between the rows. The sort will take pointers to the beginning of each row and swap them according to the contents of the rows. The rows will stay in the same places in memory.
OK, the OP has a three-column integer arrays, which is not straightforward to sort, because you can't assign arrays.
One option is to have arrays of structs, where the struct contains one element for each column, write a custom compare routine and use std::sort.
Another option is to pretend we have such an array of structs and employ the evilness of reinterpret_cast, like below:
#include <algorithm>
#include <iostream>
struct elt_t
{
int e0;
int e1;
int e2;
};
int
compare (const elt_t &a, const elt_t &b)
{
if (a.e1 == b.e1)
return a.e2 < b.e2;
else
return a.e1 < b.e1;
}
int a [10][3] =
{
{ 10, 0, 1 },
{ 11, 0, 2 },
{ 12, 1, 2 },
{ 13, 0, 1 }
};
int
main ()
{
std::sort (reinterpret_cast<elt_t *>(&a[0]),
reinterpret_cast<elt_t *>(&a[4]), compare);
int i, j;
for (i = 0; i < 4; ++i)
std::cout << a [i][0] << ", " << a [i][1] << ", " << a [i][2] << std::endl;
return 0;
}
Of course, whether or not this is standards compliant is highly debatable :)
EDIT:
With the added requirement for the matrix to by dynamically allocated, you can use an array of std::vector, or a vector of std::vector:
#include <algorithm>
#include <iostream>
#include <vector>
int
compare (const std::vector<int> &a, const std::vector<int> &b)
{
if (a[1] == b[1])
return a[2] < b[2];
else
return a[1] < b[1];
}
std::vector<int> *
make_vec (unsigned int r, unsigned int c)
{
std::vector<int> *v = new std::vector<int> [r];
/* Don't care for column count for the purposes of the example. */
v [0].push_back (10); v [0].push_back (0); v [0].push_back (1);
v [1].push_back (11); v [1].push_back (0); v [1].push_back (2);
v [2].push_back (12); v [2].push_back (1); v [2].push_back (2);
v [3].push_back (13); v [3].push_back (0); v [3].push_back (1);
return v;
}
int
main ()
{
std::vector<int> *v = make_vec (4, 3);
std::sort (&v[0], &v[4], compare);
int i, j;
for (i = 0; i < 4; ++i)
std::cout << v[i][0] << ", " << v [i][1] << ", " << v [i][2] << std::endl;
delete [] v;
return 0;
}
use this for the second column and then for the third. Now it works for single dim arrays
int *toplace(int *start, int *end)
{
int *i = start+1, *j= end-1;
while(i<=j)
{
while(*i<=*start && i<=j) {i++;}
while(*j>=*start && i<=j) {j--;}
if (i<j) std::swap(*i++,*j--);
}
std::swap(*start,*(i-1));
return i-1;
}
void quicksort(int *start, int *end)
{
if (start >= end) return;
int *temp = start;
temp = toplace(start,end);
quicksort(start,temp);
quicksort(temp+1,end);
}
You can do this using the bubble sort algorithm (http://en.wikipedia.org/wiki/Bubble_sort)
Basically iterate through all records, comparing the current record, with the next. If the current record's 2nd column is higher then swap these records. If the current record's 2nd column is equal but the 3rd column is higher, then swap also.
Continue iterating until no more swaps are made.
To use your example:
10 0 1
11 0 2
12 1 2 (swap with next)
13 0 1
10 0 1
11 0 2(swap with next)
13 0 1
12 1 2
10 0 1
13 0 1
11 0 2
12 1 2
And done!