Check if two arrays are equal or not - c++

I am trying to know if the two given arrays are equal or not, irrespective of permutation of elements but contains the same elements and frequency of all the elements must be same.
int SameArray(int arr1[], int arr2[], int N, int M)
{
unordered_map<int, int> ump;
if(N == M)
{
for(int i = 0; i < N; i++)
{
ump[arr1[i]]++;
}
for(int i = 0; i< M; i++)
{
if(ump.find(arr2[i]) != ump.end())
ump[arr2[i]]--;
}
if(ump.empty())
return 1;
}
return 0;
}
it's not showing any errors but output is always 0.

You're looking for std::is_permutation:
bool SameArray(const std::vector<int>& arr1, const std::vector<int>& arr2) {
return std::is_permutation(arr1.begin(), arr1.end(), arr2.begin(), arr2.end());
}
I took the liberty of changing your function return to bool and taking std::vectors as function parameters since this is C++ and not C.
If you're curious about how std::permutation's comparasion works, look at its example implementation.

The condition in the if statement
if(ump.empty())
is not correct. The map can not be empty provided that the passed arrays do not have zero sizes.
Instead of the condition you could use the standard algorithm std::all_of. Also there is no sense to pass the two sizes of the arrays because if they are not equal to each other then it is evident that the arrays are not equal each other.
Also the array parameters shall be specified with the qualifier const because they are not changed in the function.
Here is a demonstrative program that shows how the function can be defined.
#include <iostream>
#include <iomanip>
#include <unordered_map>
#include <iterator>
#include <algorithm>
bool SameArray( const int a1[], const int a2[], size_t n )
{
sstd::unordered_map<int, int> m;
for ( const int *p = a1; p != a1 + n; ++p ) ++m[*p];
for ( const int *p = a2; p != a2 + n; ++p ) --m[*p];
return std::all_of( std::begin( m ), std::end( m ),
[]( const auto &p) { return p.second == 0; } );
}
int main()
{
const size_t N = 20;
int a1[N] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
int a2[N] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::cout << std::boolalpha << SameArray( a1, a2, N ) << '\n';
return 0;
}
Its output is
true

You need to check if every key in the map has a value of zero. Instead of ump.empty() you can do the below code.
for (auto& it: ump) {
if(it.second != 0) {
return 0;
}
return 1;

ump[arr2[i]]--; is not going to delete the key. You have to check whether the value of each entry is zero or not. I have added below statement before return 1 -
for (auto it = ump.begin(); it != ump.end(); ++it ) if(it->second != 0) return 0;
int SameArray(int arr1[], int arr2[], int N, int M)
{
unordered_map<int, int> ump;
if(N == M)
{
for(int i = 0; i < N; i++)
{
ump[arr1[i]]++;
}
for(int i = 0; i< M; i++)
{
if(ump.find(arr2[i]) != ump.end())
ump[arr2[i]]--;
}
for (auto it = ump.begin(); it != ump.end(); ++it ) if(it->second != 0) return 0;
return 1;
}
return 0;
}

Related

C++ finding the extreme points of an algorithm

The question:
Let A be an array of n elements (that is, the elements of A are A[0], ..., A[n−1]). An element A[i] is extreme if the following conditions hold regarding A[i]:
A[i] is not the first nor the last element of A. That is, 0 < i < n–1 and either A[i−1] < A[i] > A[i+1] or A[i−1] > A[i] < A[i+1]. For example, the extreme points of an array [0, 5, 3, 6, 8, 7, 15, 9] are 5, 3, 8, 7, 15.
Write an algorithm that prints the extreme points of the given array. If there are no extreme points, the algorithm prints “SORTED”. Do you agree that an array has no extreme points if and only if it is sorted? Explain your answer.
What I have managed to do:
#include <iostream>
using namespace std;
bool extremePoint(int arr[], int n, int num, int leftNeighbour, int rightNeighbour);
int main()
{
int array[] = { 0, 5, 3, 6, 8, 7, 15, 9 };
int size = sizeof(array) / sizeof(array[0]);
for (int i = 1; i < size - 1; i++) {
// If the current element is a peak
if (extremePoint(array, size, array[i], array[i - 1], array[i + 1]))
{
cout << array[i] << " ";
}
}
return 0;
}
bool extremePoint(int arr[], int size, int num, int leftNeighbour, int rightNeighbour)
{
if (num > leftNeighbour && num > rightNeighbour)
{
return true;
}
if (num < leftNeighbour && num < rightNeighbour)
{
return true;
}
else
{
return false;
}
}
The problem:
I have managed to write the algorithm that prints the extreme points of the given array.
Can anyone please help me with this part:
If there are no extreme points, the algorithm prints “SORTED”. Do you agree that an array has no extreme points if and only if it is sorted? Explain your answer.
For starters this function
bool extremePoint(int arr[], int size, int num, int leftNeighbour, int rightNeighbour)
{
if (num > leftNeighbour && num > rightNeighbour)
{
return true;
}
if (num < leftNeighbour && num < rightNeighbour)
{
return true;
}
else
{
return false;
}
}
does not use its parameters arr and size.
The function can be written like
bool extremePoint( int num, int eftNeighbour, int rightNeighbour )
{
return leftNeighbour < num && rightNeighbour < num ||
num < leftNeighbour && num < rightNeighbour;
}
If a sequence does not contain an extreme point it does not mean that the sequence is sorted.
For example, consider the sequence
1, 2, 2, 1
On the other hand, it is obvious that a sorted sequence indeed does not have an extreme point.
Pay attention tp that this phrase
Write an algorithm that prints the extreme points of the given array.
can be interpreted as a requirement to write a separate function (algorithm).
I would write such an algorithm the following way as it is shown in the demonstrative program below
#include <iostream>
#include <iterator>
template <typename InputIterator, typename OutputIterator>
OutputIterator extreme_points( InputIterator first,
InputIterator last,
OutputIterator out )
{
if ( first != last )
{
for ( auto prev_value = *first++; first != last; )
{
auto current_value = *first;
if ( ++first != last )
{
if ( prev_value < current_value && *first < current_value ||
current_value < prev_value && current_value < *first )
{
*out++ = current_value;
}
prev_value = current_value;
}
}
}
return out;
}
int main()
{
int a[] = { 0, 5, 3, 6, 8, 7, 15, 9 };
extreme_points( std::begin( a ),
std::end( a ),
std::ostream_iterator<int>( std::cout, ", " ) );
std::cout << '\n';
return 0;
}
The program output is
5, 3, 8, 7, 15,

Deleting an even number in an array and shift the elements

I'm trying to write a code where there is a research of even numbers and then it deletes the even numbers and then shifts all the other elements.
i is for offset and are the actual position of the elements in the array.
k is the position of the even number in the array.
int k;
for(i=0; i < N; i++)
{
if(Array[i] % 2 == 0)
{
for(k=i+1; k < N; k++)
{
Array[k-1] = Array[k];
}
N--;
}
}
Array=[2,10,3,5,8,7,3,3,7,10] the even numbers should be removed, but a 10
stays in the Array=[10,3,5,7,3,3,7].
Now is more than 3 hours that I'm trying to figure out what's wrong in my code.
This appears to be some sort of homework or school assignment. So what's the actual problem with the posted code?
It is that when you remove an even number at index i, you put the number that used to be at index i + 1 down into index i. Then you continue the outer loop iteration, which will check index i + 1, which is the number that was at the original i + 2 position in the array. So the number that started out at Array[i + 1], and is now in Array[i], is never checked.
A simple way to fix this is to decrement i when you decrement N.
Though already answered, I fail to see the reason people are driving this through a double for-loop, repetitively moving data over and over, with each reduction.
I completely concur with all the advice about using containers. Further, the algorithms solution doesn't require a container (you can use it on a native array), but containers still make it easier and cleaner. That said...
I described this algorithm in general-comment above. you don't need nested loops fr this. You need a read pointer and a write pointer. that's it.
#include <iostream>
size_t remove_even(int *arr, size_t n)
{
int *rptr = arr, *wptr = arr;
while (n-- > 0)
{
if (*rptr % 2 != 0)
*wptr++ = *rptr;
++rptr;
}
return (wptr - arr);
}
int main()
{
int arr[] = { 2,10,3,5,8,7,3,3,7,10 };
size_t n = remove_even(arr, sizeof arr / sizeof *arr);
for (size_t i=0; i<n; ++i)
std::cout << arr[i] << ' ';
std::cout << '\n';
}
Output
3 5 7 3 3 7
If you think it doesn't make a difference, I invite you to fill an array with a million random integers, then try both solutions (the nested-for-loop approach vs. what you see above).
Using std::remove_if on a native array.
Provided only for clarity, the code above basically does what the standard algorithm std::remove_if does. All we need do is provide iterators (the array offsets and size will work nicely), and know how to interpret the results.
#include <iostream>
#include <algorithm>
int main()
{
int arr[] = { 2,10,3,5,8,7,3,3,7,10 };
auto it = std::remove_if(std::begin(arr), std::end(arr),
[](int x){ return x%2 == 0; });
for (size_t i=0; i<(it - arr); ++i)
std::cout << arr[i] << ' ';
std::cout << '\n';
}
Same results.
The idiomatic solution in C++ would be to use a STL algorithm.
This example use a C-style array.
int Array[100] = {2,10,3,5,8,7,3,3,7,10};
int N = 10;
// our remove_if predicate
auto removeEvenExceptFirst10 = [first10 = true](int const& num) mutable {
if (num == 10 && first10) {
first10 = false;
return false;
}
return num % 2 == 0;
};
auto newN = std::remove_if(
std::begin(Array), std::begin(Array) + N,
removeEvenExceptFirst10
);
N = std::distance(std::begin(Array), newN);
Live demo
You could use a std::vector and the standard function std::erase_if + the vectors erase function to do this:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> Array = {2, 10, 3, 5, 8, 7, 3, 3, 7, 10};
auto it = std::remove_if(
Array.begin(),
Array.end(),
[](int x) { return (x & 1) == 0 && x != 10; }
);
Array.erase(it, Array.end());
for(int x : Array) {
std::cout << x << "\n";
}
}
Output:
10
3
5
7
3
3
7
10
Edit: Doing it the hard way:
#include <iostream>
int main() {
int Array[] = {2, 10, 3, 5, 8, 7, 3, 3, 7, 10};
size_t N = sizeof(Array) / sizeof(int);
for(size_t i = 0; i < N;) {
if((Array[i] & 1) == 0 && Array[i] != 10) {
for(size_t k = i + 1; k < N; ++k) {
Array[k - 1] = Array[k];
}
--N;
} else
++i; // only step i if you didn't shift the other values down
}
for(size_t i = 0; i < N; ++i) {
std::cout << Array[i] << "\n";
}
}
Or simpler:
#include <iostream>
int main() {
int Array[] = {2, 10, 3, 5, 8, 7, 3, 3, 7, 10};
size_t N = sizeof(Array) / sizeof(int);
size_t k = 0;
for(size_t i = 0; i < N; ++i) {
if((Array[i] & 1) || Array[i] == 10) {
// step k after having saved this value
Array[k++] = Array[i];
}
}
N = k;
for(size_t i = 0; i < N; ++i) {
std::cout << Array[i] << "\n";
}
}

copy and cancel int array

I got two arrays, both are sorted. One array is filled with repeating values, the other one filled with values that shall be cancelled in the first array. For example:
int * val = new int[11];
val[0] = 1; val[1] = 1;
val[2] = 2; val[3] = 2; val[4] = 2; val[5] = 2;
val[6] = 3;
val[7] = 4;
val[8] = 5; val[9] = 5; val[10] = 5;
int * invalid = new int[2]; invalid[0] = 2; invalid[1] = 5;
Then the output shall be like this
int * valid = new int[4];
valid[0] = 1; valid[1] = 1;
valid[2] = 3;
valid[3] = 4;
How can I implement this efficiently using a for loop? I want to point out that I do not want to switch to containers like vector or list, because I know there will be comments going in that direction. I explicitly want work with arrays.
If both are sorted, this is just a simple O(N+M) algorithm: start with both arrays at zero index, and increment the one pointing to the smaller value. If you incremented the target array, copy unless it equals the invalid array.
Also, since you are only removing items, you can avoid some copies if you don't have to keep the original data: you can keep a counter how many items you discarded, and copy into the same array to currentIdx-discardedCount if discardedCount is greater than zero.
At first you should count the number of elements in the source array that satisfy the condition and then allocate enough memory for the elements.
Here is a demonstrative program
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
const size_t N1 = 11;
const size_t N2 = 2;
int * val = new int[N1] { 1, 1, 2, 2, 2, 2, 3, 4, 5, 5, 5 };
int * invalid = new int[N2] { 2, 5 };
int *valid = nullptr;
auto n = std::count_if( val, val + N1,
[=]( int x ) { return !std::binary_search( invalid, invalid + N2, x ); } );
if ( n )
{
valid = new int[n];
std::copy_if( val, val + N1, valid,
[=]( int x ) { return !std::binary_search( invalid, invalid + N2, x ); } );
}
if ( valid ) std::copy( valid, valid + n, std::ostream_iterator<int>( std::cout, " " ) );
std::cout << std::endl;
return 0;
}
Its output is
1 1 3 4
You can use standard algorithm std::binary search if the invalid array has many elements or you can just write the lambda expression like
[=]( int x ) { return x != invalid[0] && x != invalid[1]; }
For example
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
const size_t N1 = 11;
const size_t N2 = 2;
int * val = new int[N1] { 1, 1, 2, 2, 2, 2, 3, 4, 5, 5, 5 };
int * invalid = new int[N2] { 2, 5 };
int *valid = nullptr;
auto is_valid_element = [=]( int x ) { return x != invalid[0] && x != invalid[1]; };
auto n = std::count_if( val, val + N1, is_valid_element );
if ( n )
{
valid = new int[n];
std::copy_if( val, val + N1, valid, is_valid_element );
}
if ( valid ) std::copy( valid, valid + n, std::ostream_iterator<int>( std::cout, " " ) );
std::cout << std::endl;
return 0;
}
The compiler should support C++ 2011.
#include <iostream>
const int SIZE_1 = 11;
const int SIZE_2 = 2;
/*find out if item should be exclude from result array; this take linear time over the size of the invalids array*/
bool doNotInclude(int item, int invalids[], int size)
{
bool remove = false;
for(int i = 0; i < size; i++)
{
if(invalids[i] == item)
{
remove = true;
}
}
return remove;
}
int main() {
//array of values
int * val = new int[SIZE_1] { 1, 5, 2, 2, 2, 2, 3, 4, 1, 5, 5 };
//values to ignore
int * invalid = new int[SIZE_2] { 2, 5 };
//result array
int *valid = new int[SIZE_1];
//keep track of result array current index/ size
int currentIndex = 0;
/*check if elements of input array are in invalids, if not put them in the result array*/
for(int i = 0; i < SIZE_1; i++)
{
if(!doNotInclude(val[i], invalid, SIZE_2))
{
valid[currentIndex] = val[i];
currentIndex++;
}
}
//print result
//currentIndex is now the size of the valid array
for(int n = 0; n < currentIndex; n++)
{
std::cout << valid[n] << ' ';
}
}
This method of doing it is O(N*M) whether the arrays are sorted or not.
Conceptually, an algorithm like this pseudo-code:
int i, j;
j = 0;
for (i=0; i < length(val); i++) {
if (val[i] != VALUE_TO_DELETE) {
val[j++] = val[i];
}
}
... now discard, or ignore, anything in "val" beyond element #j.
We simply iterate through the array, copying anything that is not the value we want to get rid of. i is the cursor used to find values, and j says where to put them.
Values beyond element #j are still there, physically, but you ignore them.
For the sake of completeness, if we are looking for invalid numbers:
int i, j, k;
boolean delete_me;
j = 0;
for (i=0; i < length(val); i++) {
// search the "invalid" list to see if the number is in it
delete_me = false;
for (k = 0; k < length(invalid); k++) {
if (val[i] == invalid[k]) {
delete_me = true;
break; // quit the loop as soon as we know ...
}
}
// copy what is NOT in it
if (!delete_me) { // notice: "if NOT" ...
val[j++] = val[i];
}
}

print non common elements from two arrays

I am trying to print the non common elements between two arrays. For example,
if array1 = { 1, 3, 5} and array2 = {1, 2, 4, 5}, my output should be {2, 3, 4}.
I have tried something here. But it prints only 3.
What am I doing wrong?
#include<iostream>
using namespace std;
int main()
{
int a[] = { 1, 3, 5 };
int b[] = { 1, 2, 4, 5 };
bool contains = false;
int result[10];
int r = 0;
int x;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
if (a[i] == b[j]) {
contains = true;
break;
}
}
if (!contains) {
result[r]=a[i];
++r;
}
else{
contains = false;
}
}
for (x = 0; x < r; x++)
{
cout<< result[x]<<"\n";
}
return 0;
}
You did not add the unique values from b to result. But this is c++. I recommend to use std::vector, std::sort, std::set_symmetric_difference and std::back_inserter.
#include <iostream> // std::cout
#include <algorithm> // std::set_symmetric_difference, std::sort
#include <iterator> // std::back_inserter
#include <vector> // std::vector
int main()
{
std::vector< int > a = { 1, 3, 5 };
std::vector< int > b = { 1, 2, 4, 5 };
std::sort( a.begin(), a.end() );
std::sort( b.begin(), b.end() );
std::vector< int > result;
std::set_symmetric_difference( a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(result) );
for ( int x : result )
std::cout << x << "\n";
return 0;
}
Live Example
As suggested by #ChristianHackl in the comment below, it is also possible to use arrays for a and b and using the free-standing functions std::begin and std::end:
#include <iostream> // std::cout
#include <algorithm> // std::set_symmetric_difference, std::sort
#include <iterator> // std::back_inserter
#include <vector> // std::vector, std::begin, std::end
int main()
{
int a[]{ 1, 3, 5 };
int b[]{ 1, 2, 4, 5 };
std::sort( std::begin(a), std::end(a) );
std::sort( std::begin(b), std::end(b) );
std::vector< int > result;
std::set_symmetric_difference( std::begin(a), std::end(a), std::begin(b), std::end(b), std::back_inserter(result) );
for ( int x : result )
std::cout << x << "\n";
return 0;
}
You added all the "unique" values from a to the result but you forgot to add all the values from b to the result.
EDIT
Something like that:
for (int i=0; i < sizeof(b)/sizeof(int); ++i, ++r)
{
result[r] = b[i];
}
Your algorithmics is wrong here. For one thing your code runs in o(a*b) where a and b are the list lengths.
Besides, it only produces elements that are in A but not in B.
The way to do this is to sort both lists, then browse through A and B, moving to the smallest current element and adding it to the result if both current elements are different.
This will run in o(log a + log b + a + b).

Generating combinations in C++

I have been searching for a source code for generating combinations using C++. I found some advanced codes for this but that is good for only specific number predefined data. Can anyone give me some hints, or perhaps, some ideas to generate a combination?
As an example, suppose the set S = { 1, 2, 3, ...., n} and we pick r= 2 out of it. The input would be n and r. In this case, the program will generate arrays of length two. So input of 5 2 would output 1 2, 1 3.
I had difficulty in constructing the algorithm. It took me a month to think about this.
A simple way using std::next_permutation:
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
int n, r;
std::cin >> n;
std::cin >> r;
std::vector<bool> v(n);
std::fill(v.end() - r, v.end(), true);
do {
for (int i = 0; i < n; ++i) {
if (v[i]) {
std::cout << (i + 1) << " ";
}
}
std::cout << "\n";
} while (std::next_permutation(v.begin(), v.end()));
return 0;
}
or a slight variation that outputs the results in an easier to follow order:
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
int n, r;
std::cin >> n;
std::cin >> r;
std::vector<bool> v(n);
std::fill(v.begin(), v.begin() + r, true);
do {
for (int i = 0; i < n; ++i) {
if (v[i]) {
std::cout << (i + 1) << " ";
}
}
std::cout << "\n";
} while (std::prev_permutation(v.begin(), v.end()));
return 0;
}
A bit of explanation:
It works by creating a "selection array" (v), where we place r selectors, then we create all permutations of these selectors, and print the corresponding set member if it is selected in in the current permutation of v.
You can implement it if you note that for each level r you select a number from 1 to n.
In C++, we need to 'manually' keep the state between calls that produces results (a combination): so, we build a class that on construction initialize the state, and has a member that on each call returns the combination while there are solutions: for instance
#include <iostream>
#include <iterator>
#include <vector>
#include <cstdlib>
using namespace std;
struct combinations
{
typedef vector<int> combination_t;
// initialize status
combinations(int N, int R) :
completed(N < 1 || R > N),
generated(0),
N(N), R(R)
{
for (int c = 1; c <= R; ++c)
curr.push_back(c);
}
// true while there are more solutions
bool completed;
// count how many generated
int generated;
// get current and compute next combination
combination_t next()
{
combination_t ret = curr;
// find what to increment
completed = true;
for (int i = R - 1; i >= 0; --i)
if (curr[i] < N - R + i + 1)
{
int j = curr[i] + 1;
while (i <= R-1)
curr[i++] = j++;
completed = false;
++generated;
break;
}
return ret;
}
private:
int N, R;
combination_t curr;
};
int main(int argc, char **argv)
{
int N = argc >= 2 ? atoi(argv[1]) : 5;
int R = argc >= 3 ? atoi(argv[2]) : 2;
combinations cs(N, R);
while (!cs.completed)
{
combinations::combination_t c = cs.next();
copy(c.begin(), c.end(), ostream_iterator<int>(cout, ","));
cout << endl;
}
return cs.generated;
}
test output:
1,2,
1,3,
1,4,
1,5,
2,3,
2,4,
2,5,
3,4,
3,5,
4,5,
my simple and efficient solution based on algorithms from Prof. Nathan Wodarz:
// n choose r combination
#include <vector>
#include <iostream>
#include <algorithm>
struct c_unique {
int current;
c_unique() {current=0;}
int operator()() {return ++current;}
} UniqueNumber;
void myfunction (int i) {
std::cout << i << ' ';
}
int main()
{
int n=5;
int r=3;
std::vector<int> myints(r);
std::vector<int>::iterator first = myints.begin(), last = myints.end();
std::generate(first, last, UniqueNumber);
std::for_each(first, last, myfunction);
std::cout << std::endl;
while((*first) != n-r+1){
std::vector<int>::iterator mt = last;
while (*(--mt) == n-(last-mt)+1);
(*mt)++;
while (++mt != last) *mt = *(mt-1)+1;
std::for_each(first, last, myfunction);
std::cout << std::endl;
}
}
then output is:
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
#include<iostream>
using namespace std;
for(int i=1;i<=5;i++)
for (int j=2;j<=5;j++)
if (i!=j)
cout<<i<<","<<j<<","<<endl;
//or instead of cout... you can put them in a matrix n x 2 and use the solution
Code is similar to generating binary digits. Keep an extra data structure, an array perm[], whose value at index i will tell if ith array element is included or not. And also keep a count variable. Whenever count == length of combination, print elements based on perm[].
#include<stdio.h>
// a[] : given array of chars
// perm[] : perm[i] is 1 if a[i] is considered, else 0
// index : subscript of perm which is to be 0ed and 1ed
// n : length of the given input array
// k : length of the permuted string
void combinate(char a[], int perm[],int index, int n, int k)
{
static int count = 0;
if( count == k )
{
for(int i=0; i<n; i++)
if( perm[i]==1)
printf("%c",a[i]);
printf("\n");
} else if( (n-index)>= (k-count) ){
perm[index]=1;
count++;
combinate(a,perm,index+1,n,k);
perm[index]=0;
count--;
combinate(a,perm,index+1,n,k);
}
}
int main()
{
char a[] ={'a','b','c','d'};
int perm[4] = {0};
combinate(a,perm,0,4,3);
return 0;
}
this is a recursive method, which you can use on any type. you can iterate on an instance of Combinations class (e.g. or get() vector with all combinations, each combination is a vector of objects. This is written in C++11.
//combinations.hpp
#include <vector>
template<typename T> class Combinations {
// Combinations(std::vector<T> s, int m) iterate all Combinations without repetition
// from set s of size m s = {0,1,2,3,4,5} all permuations are: {0, 1, 2}, {0, 1,3},
// {0, 1, 4}, {0, 1, 5}, {0, 2, 3}, {0, 2, 4}, {0, 2, 5}, {0, 3, 4}, {0, 3, 5},
// {0, 4, 5}, {1, 2, 3}, {1, 2, 4}, {1, 2, 5}, {1, 3, 4}, {1, 3, 5}, {1, 4, 5},
// {2, 3, 4}, {2, 3, 5}, {2, 4, 5}, {3, 4, 5}
public:
Combinations(std::vector<T> s, int m) : M(m), set(s), partial(std::vector<T>(M))
{
N = s.size(); // unsigned long can't be casted to int in initialization
out = std::vector<std::vector<T>>(comb(N,M), std::vector<T>(M)); // allocate space
generate(0, N-1, M-1);
};
typedef typename std::vector<std::vector<T>>::const_iterator const_iterator;
typedef typename std::vector<std::vector<T>>::iterator iterator;
iterator begin() { return out.begin(); }
iterator end() { return out.end(); }
std::vector<std::vector<T>> get() { return out; }
private:
void generate(int i, int j, int m);
unsigned long long comb(unsigned long long n, unsigned long long k); // C(n, k) = n! / (n-k)!
int N;
int M;
std::vector<T> set;
std::vector<T> partial;
std::vector<std::vector<T>> out;
int count (0);
};
template<typename T>
void Combinations<T>::generate(int i, int j, int m) {
// combination of size m (number of slots) out of set[i..j]
if (m > 0) {
for (int z=i; z<j-m+1; z++) {
partial[M-m-1]=set[z]; // add element to permutation
generate(z+1, j, m-1);
}
} else {
// last position
for (int z=i; z<j-m+1; z++) {
partial[M-m-1] = set[z];
out[count++] = std::vector<T>(partial); // add to output vector
}
}
}
template<typename T>
unsigned long long
Combinations<T>::comb(unsigned long long n, unsigned long long k) {
// this is from Knuth vol 3
if (k > n) {
return 0;
}
unsigned long long r = 1;
for (unsigned long long d = 1; d <= k; ++d) {
r *= n--;
r /= d;
}
return r;
}
Test file:
// test.cpp
// compile with: gcc -O3 -Wall -std=c++11 -lstdc++ -o test test.cpp
#include <iostream>
#include "combinations.hpp"
struct Bla{
float x, y, z;
};
int main() {
std::vector<int> s{0,1,2,3,4,5};
std::vector<Bla> ss{{1, .4, 5.0},{2, .7, 5.0},{3, .1, 2.0},{4, .66, 99.0}};
Combinations<int> c(s,3);
// iterate over all combinations
for (auto x : c) { for (auto ii : x) std::cout << ii << ", "; std::cout << "\n"; }
// or get a vector back
std::vector<std::vector<int>> z = c.get();
std::cout << "\n\n";
Combinations<Bla> cc(ss, 2);
// combinations of arbitrary objects
for (auto x : cc) { for (auto b : x) std::cout << "(" << b.x << ", " << b.y << ", " << b.z << "), "; std::cout << "\n"; }
}
output is :
0, 1, 2,
0, 1, 3,
0, 1, 4,
0, 1, 5,
0, 2, 3,
0, 2, 4,
0, 2, 5,
0, 3, 4,
0, 3, 5,
0, 4, 5,
1, 2, 3,
1, 2, 4,
1, 2, 5,
1, 3, 4,
1, 3, 5,
1, 4, 5,
2, 3, 4,
2, 3, 5,
2, 4, 5,
3, 4, 5,
(1, 0.4, 5), (2, 0.7, 5),
(1, 0.4, 5), (3, 0.1, 2),
(1, 0.4, 5), (4, 0.66, 99),
(2, 0.7, 5), (3, 0.1, 2),
(2, 0.7, 5), (4, 0.66, 99),
(3, 0.1, 2), (4, 0.66, 99),
Below is an iterative algorithm in C++ that does not use the STL nor recursion nor conditional nested loops. It is faster that way, it does not perform any element swaps and it does not burden the stack with recursion and it can also be easily ported to ANSI C by substituting mallloc(), free() and printf() for new, delete and std::cout, respectively.
If you want the displayed elements to start from 1 then change the OutputArray() function. Namely: cout << ka[i]+1... instead of cout << ka[i]....
Note that I use K instead of r.
void OutputArray(unsigned int* ka, size_t n) {
for (int i = 0; i < n; i++)
std::cout << ka[i] << ",";
std::cout << endl;
}
void GenCombinations(const unsigned int N, const unsigned int K) {
unsigned int *ka = new unsigned int [K]; //dynamically allocate an array of UINTs
unsigned int ki = K-1; //Point ki to the last elemet of the array
ka[ki] = N-1; //Prime the last elemet of the array.
while (true) {
unsigned int tmp = ka[ki]; //Optimization to prevent reading ka[ki] repeatedly
while (ki) //Fill to the left with consecutive descending values (blue squares)
ka[--ki] = --tmp;
OutputArray(ka, K);
while (--ka[ki] == ki) { //Decrement and check if the resulting value equals the index (bright green squares)
OutputArray(ka, K);
if (++ki == K) { //Exit condition (all of the values in the array are flush to the left)
delete[] ka;
return;
}
}
}
}
int main(int argc, char *argv[])
{
GenCombinations(7, 4);
return 0;
}
Combinations: Out of "7 Choose 4".
I'd suggest figuring out how you would do it on paper yourself and infer pseudocode from that. After that, you only need to decide the way to encode and store the manipulated data.
For ex:
For each result item in result array // 0, 1, ... r
For each item possible // 0, 1, 2, ... n
if current item does not exist in the result array
place item in result array
exit the inner for
end if
end for
end for
You can use recursion whereby to pick N+1 combinations you pick N combinations then add 1 to it. The 1 you add must always be after the last one of your N, so if your N includes the last element there are no N+1 combinations associated with it.
Perhaps not the most efficient solution but it should work.
Base case would be picking 0 or 1. You could pick 0 and get an empty set. From an empty set you can assume that iterators work between the elements and not at them.
Here are my attempt:
Function (ready for copy/paste) without any dependency
template<class _Tnumber, class _Titerator >
bool next_combination
(
_Titerator const& _First
, _Titerator const& _Last
, _Tnumber const& _Max //!< Upper bound. Not reachable
)
{
_Titerator _Current = _First;
if( _Current == _Last )
{
return false;
}
*_Current += 1;
if( *_Current < _Max )
{
return true;
}
_Titerator _Next = _Current + 1;
if( _Next == _Last )
{
return false;
}
if( false == next_combination( _Next, _Last, _Max - 1 ) )
{
return false;
}
*_Current = *_Next + 1;
return *_Current < _Max;
}
Test:
vector<int> vec({3,2,1}); // In descending order and different
do
{
copy( vec.begin(), vec.end(), ostream_iterator<int>(cout, ", " ) ); cout << endl;
}while( ::math::algorithm::next_combination( vec.begin(), vec.end(), 6 ) );
And output:
3, 2, 1,
4, 2, 1,
5, 2, 1,
4, 3, 1,
5, 3, 1,
5, 4, 1,
4, 3, 2,
5, 3, 2,
5, 4, 2,
5, 4, 3,
void print(int *a, int* s, int ls)
{
for(int i = 0; i < ls; i++)
{
cout << a[s[i]] << " ";
}
cout << endl;
}
void PrintCombinations(int *a, int l, int k, int *s, int ls, int sp)
{
if(k == 0)
{
print(a,s,ls);
return;
}
for(int i = sp; i < l; i++)
{
s[k-1] = i;
PrintCombinations(a,l,k-1,s,ls,i+1);
s[k-1] = -1;
}
}
int main()
{
int e[] = {1,2,3,4,5,6,7,8,9};
int s[] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
PrintCombinations(e,9,6,s,6,0);
}
For the special case of (n choose r), where r is a fixed constant, we can write r nested loops to arrive at the situation. Sometimes when r is not fixed, we may have another special case (n choose n-r), where r is again a fixed constant. The idea is that every such combination is the inverse of the combinations of (n choose r). So we can again use r nested loops, but invert the solution:
// example 1: choose each 2 from given vector and apply 'doSomething'
void doOnCombinationsOfTwo(const std::vector<T> vector) {
for (int i1 = 0; i1 < vector.size() - 1; i1++) {
for (int i2 = i1 + 1; i2 < vector.size(); i2++) {
doSomething( { vector[i1], vector[i2] });
}
}
}
// example 2: choose each n-2 from given vector and apply 'doSomethingElse'
void doOnCombinationsOfNMinusTwo(const std::vector<T> vector) {
std::vector<T> combination(vector.size() - 2); // let's reuse our combination vector
for (int i1 = 0; i1 < vector.size() - 1; i1++) {
for (int i2 = i1 + 1; i2 < vector.size(); i2++) {
auto combinationEntry = combination.begin(); // use iterator to fill combination
for (int i = 0; i < vector.size(); i++) {
if (i != i1 && i != i2) {
*combinationEntry++ = i;
}
}
doSomethingElse(combinationVector);
}
}
}
This seems readable and also it works for std::vector, std::list, std::deque or even static declared int intArray[]
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <list>
#include <set>
#include <iterator>
template<typename InputIt, typename T>
bool nextCombination(InputIt begin,
InputIt end,
T toElement) {
/*
Given sequence: 1 2 3 4 5
Final sequence: 6 7 8 9 10
-- Formally --
Given sequence: 1 2 ... k-1 k
Final sequence: (n-k+1) (n-k+2) ... (n-1) n
lengthOfSubsequence = positionOf(5) - positionOf(1) = 5
We look for an element that satisfies:
seqeunce[pos] < n - k + pos
*/
const auto lengthOfSubsequence = std::distance(begin, end);
auto viewed_element_it = std::make_reverse_iterator(end);
auto reversed_begin = std::make_reverse_iterator(begin);
/*Looking for this element here*/
while ((viewed_element_it != reversed_begin) &&
(*viewed_element_it >= toElement -
lengthOfSubsequence +
std::distance(viewed_element_it, reversed_begin))) {
//std::distance shows position of element in subsequence here
viewed_element_it++;
}
if (viewed_element_it == reversed_begin)
return false;
auto it = std::prev(viewed_element_it.base());
/*
Increment the found element.
The rest following elements we set as seqeunce[pos] = seqeunce[pos-1] + 1
*/
std::iota(it, end, *it + 1);
return true;
}
int main()
{
std::list<int> vec = { 1, 2, 3 };
do {
std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
} while (nextCombination(vec.begin(), vec.end(), 10));
}
One can directly compute all combinations indices in lexicographical order, like I did in following code.
These indices can be used for direct output or as pointers to any combined items as "abcde" string in second example of main() function, see output example after code.
Try it online!
#include <vector>
#include <iostream>
template <typename F>
void Combinations(size_t n, size_t k, F && out) {
if (k > n)
return;
std::vector<size_t> a(k);
for (size_t i = 0; i < k; ++i)
a[i] = i;
while (true) {
out(a);
int i = int(k) - 1;
while (i >= 0 && a[i] >= n - 1 - (k - 1 - i))
--i;
if (i < 0)
break;
for (size_t j = a[i] + 1; i < k; ++j, ++i)
a[i] = j;
}
}
int main() {
Combinations(5, 3, [](auto const & a){
for (auto i: a)
std::cout << i << " ";
std::cout << std::endl;
});
std::string s = "abcde";
Combinations(5, 3, [&](auto const & a){
for (auto i: a)
std::cout << s[i] << " ";
std::cout << std::endl;
});
}
Output:
0 1 2
0 1 3
0 1 4
0 2 3
0 2 4
0 3 4
1 2 3
1 2 4
1 3 4
2 3 4
a b c
a b d
a b e
a c d
a c e
a d e
b c d
b c e
b d e
c d e
vector<list<int>> generate(int N, int K, int& count) {
vector<list<int>> output;
if(K == 1) {
count = N;
for(int i = 1; i <= N; i++) {
list<int> l = {i};
output.push_back(l);
}
} else {
count = 0;
int n;
vector<list<int>> l = generate(N, K - 1, n);
for(auto iter = l.begin(); iter != l.end(); iter++) {
int last = iter->back();
for (int i = last + 1; i <= N; ++i) {
list<int> value = *iter;
value.push_back(i);
output.push_back(value);
count++;
}
}
}
return output;
}
You can just use for loops if r is small, here r = 2, so two for loops:
unsigned int i, j, max=0;
for(i=1; i<=n; i++){
for(j=i+1; j<=n; j++){
int ans = (i & j);
cout << i << " " << j << endl;
}
}