c++ checking an array for a specific range of values? - c++

i would like to check an array for a specific range of values.
ie, the range of values is from 0 --> 9 and the actual array is 50 elements large.
i also want to keep track of how many of each value there is.
ie, if there are 3 zeroes, 8 ones and 5 two's, then my final vector should look like, 3 8 5.
i was able to solve it with the code below BUT, i realized that my range values needs to be equal to my array size, otherwise it does not check all elements.
is there a better way to do this?
int main() {
int intensityRange = 10;
int cloudSize = 10;
int cloud [] = {0, 3, 3, 2, 1, 5, 2, 3, 5, 2};
vector <int> totalGreyValues;
int k = 0;
for (int i = 0; i < intensityRange; i++) {
for (int j = 0; j < cloudSize; j++) {
if (cloud[j] == i) {
k = k + 1;
cout << " " << k;
}
else
cout << " no match ";
}
totalGreyValues.push_back (k);
k = 0;
}
cout << endl << endl << totalGreyValues.size();
for (int h = 0; h < totalGreyValues.size(); h ++)
cout << " " << totalGreyValues[h];
// values --> 0 1 2 3 4 5 6 7 8 9
// answer --> 1 1 3 3 0 2 0 0 0 0
return 0;
}

It's much easier to use std::map:
int size = 50;
int data[size] = { 1, 2, 3, 4, 5, ... };
std::map<int, int> mymap;
for(int i = 0; i < size; i++)
{
if(data[i] >= min && data[i] <= max)
mymap[data[i]] = mymap[data[i]] + 1;
}
This saves some space, because you don't save unused values and the loop count is also much smaller, because you only process once per value.

If your range is continuous I would prefer a boost::vector_property_map.
#include <boost/property_map/vector_property_map.hpp>
#include <iostream>
int main()
{
boost::vector_property_map<unsigned int> m(10); // size of expected range
std::vector<int> cloud = {0, 3, 3, 2, 1, 5, 2, 3, 5, 2};
for(auto x : cloud) { m[x]++; }
for(auto it = m.storage_begin(); it != m.storage_end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}
If your range does not start at 0 you can use IndexMap template
argument to remap the indices. This will also work if you map a non
continous set of values that you want to count into a continous
range. You might need to perform a check if you only want to count
specific values, but given the expensiveness of the count operation,
I'd rather count them all instead of checking what to count.

Use a std::map and the std::accumulate function:
#include <map>
#include <algorithm>
typedef std::map<int, int> Histogram;
Histogram& addIfInRange(Histogram& histogram, const int value)
{
if(inRange(value))
{
++histogram[value];
}
// else don't add it
return histogram;
}
Histogram histogram =
std::accumulate(data, data + size, Histogram(), addIfInRange);

If you have large enough empty regions, you can try a multiset, together with some of C++' new facilities:
#include <set>
#include <iostream>
int main () {
int vals[] = { 0, 1, 2, 3, 4, 5, 5, 5, 6 };
std::multiset <int> hist;
for (auto const &v : vals)
if (v >= 3 && v <= 5) hist.insert (v);
for (auto const &v : hist)
std::cout << v << " -> " << hist.count (v) << '\n';
}
If your data is densely populated, a std::vector might give superiour results:
#include <algorithm>
#include <iostream>
int main () {
using std::begin; using std::end;
int vals[] = { 1, 2, 4, 5, 5, 5, 6 };
const auto val_mm = std::minmax_element (begin(vals), end(vals));
const int val_min = *val_mm.first,
val_max = *val_mm.second + 1;
std::vector<int> hist (val_max - val_min);
for (auto v : vals)
++hist [v - val_min];
for (auto v : vals)
std::cout << v << " -> " << hist[v-val_min] << '\n';
}

Related

Heapify a Vector in C++

I am trying to heapify a given vector passed by reference to a function. The function takes a reference to a vector as an argument and heapifies it. I'm also trying to calculate how many positions in the vector changed value as compared to the starting point. I'd like to update this difference variable inside the function.
For each position in the new and old vector: if the positions have a different value: diff++
Here's What I Have:
void heapify(std::vector<int> &v, int &diff)
{
int max = diff;
int l = 2 * diff + 1;
int r = 2 * diff + 2;
if (l < (int)v.size() && v[l] > v[diff])
diff = l;
if (r < (int)v.size() && v[r] > v[diff])
diff = r;
if (max != diff) {
swap(v[max], v[diff]);
heapify(v, diff);
}
}
int main()
{
vector<int> v = {20, 19, 100, 2};
int diff = 0;
heapify(v, diff);
cout << "Different in " << diff << " positions. Heap: ";
for(int i: v)
cout << i << ", ";
cout << endl;
return 0;
}
It is really close. A couple of glitches: for a one item vector, the contents shouldn't change. For a vector that's smallest to largest from 1 to 10, the difference is off by 2. For a really large random vector, the difference is off by 1.
Using std::make_heap
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> v = {20, 19, 100, 2};
std::make_heap(v.begin(), v.end());
for(int i: v)
std::cout << i << ", ";
std::cout << std::endl;
return 0;
}
prints:
100, 19, 20, 2,

Can't display the correct frequency of integers in an array

I just started with C++. The prompt is to " display the frequency of integers in the given array "
The following is the code that I have written:
#include <iostream>
#include <array>
using namespace std;
int main()
{
array <unsigned int,20> n = {1, 2, 5, 4, 3, 5, 2, 1, 3, 1, 4, 3, 3, 3, 2, 3, 3, 2, 2};
for(size_t i = 0; i < n[i]; i++)
{
int count = 0;
for(size_t j = 0; j < n.size(); j++)
{
if (n[i] == n[j])
{
count++;
}
}
cout<<"Frequency of "<<n[i]<<" is "<<count<<endl;
}
return 0;
}
But my output is :
Frequency of 1 is 3
Frequency of 2 is 5
Frequency of 5 is 2
Frequency of 4 is 2
Why isn't the frequency of 3 showing up? I am pretty sure it's a silly mistake but I can't pin point where.
Here's a simple way to count frequencies of values:
std::map<int, int> freq;
for (int const i : n)
freq[i]++; // map has the nice property that it
// defaults the value of a key to 0
for (auto const &[i, count] : freq) // this loop needs c++17
std::cout << "Frequency of " << i << " is " << count << std::endl;
Because this:
for(size_t i = 0; i < n[i]; i++)
// ^^^^
…is wrong.
You should be going up to n.size().
Currently, you're only going up to what happens to be 4 (n[4] is 3, and 4 < 3 does not hold).
This was done right for the loop over j.
As others have pointed out that there are far better ways to do this.
Such as hashing
You can read About these here: https://www.geeksforgeeks.org/counting-frequencies-of-array-elements/
Now I am gonna point out exactly where you went wrong.
in the first for loop replace i < n[i] with i<n.size()
Wrong:
for(size_t i = 0; i < n[i]; i++)
Correct :
for (size_t i = 0; i < n.size(); i++)
Your code fails as when for i=3 the value of n[i]=3 which violated your for loop condition
Here this code will run for all repetitions of a number so it will print the same results multiple times and also will do all the calculation so maintain a
A visited array that stores the no which you have already calculated.
Here is your code but Corrected
#include <iostream>
#include <array>
#include <vector>
using namespace std;
int main()
{
array<unsigned int, 20> n = {1, 2, 5, 4, 3, 5, 2, 1, 3, 1, 4, 3, 3, 3, 2, 3, 3, 2, 2};
vector<bool> visited(n.size(), false);
for (size_t i = 0; i < n.size(); i++)
{
int count = 0;
// Skip this element if already processed
if (visited[i] == true) continue;
for (size_t j = 0; j < n.size(); j++){
if (n[i] == n[j]){
count++;
// marking indexes already visited
visited[j] = true;
}
}
cout << "Frequency of " << n[i] << " is " << count << endl;
}
return 0;
}
But the best option is to learn Maps they are extremely helpful and are very easy to implement.
https://www.geeksforgeeks.org/map-associative-containers-the-c-standard-template-library-stl/
As you use std::array so i assume you are fimiliar with STL so why not use its power to solve the problem.
Find The unique elemets first from your array.
std::unordered_set<int> s(n.begin(), n.end());
Than simply use count to give count of every element in your array.
#include <algorithm>
#include <array>
#include <iostream>
#include <unordered_set>
int main()
{
std::array<unsigned int, 20> n = { 1, 2, 5, 4, 3, 5, 2, 1, 3, 1, 4, 3, 3, 3, 2, 3, 3, 2, 2 };
std::unordered_set<int> s(n.begin(), n.end());
for (const auto& itr : s) {
std::cout << "Count of "<< itr << " Is equal to = " <<std::count(n.begin(), n.end(), itr) << std::endl;
}
}

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";
}
}

Algorithm for deleting multiple array elements and shifting array

I have an array let's say with 5 items, if element[i] is less than 3 need to move element[i+1] in place of element[i].
int array[5] = {4, 2, 3, 5, 1};
int number = 3;
for (int i = 0; i < number; i++)
{
if (array[i] > number)
{
for (int j = 0; j < i - 1; j++)
{
array[j] = array[j + 1];
}
number = number - 1;
}
}
expected result is array = {2, 3, 1, anyNumber, anyNumber};
A O(n) working code for the above problem.. But as others pointed out in the comments.. You end up with an array that is using less space then allocated to it..
#include<stdio.h>
int main()
{
int arr[] = {4, 2, 3, 5, 1};
int* temp1 = arr;
int* temp2 = arr;
int i, n1 = 5, n2 = 5;
for(i = 0; i < n1; i++)
{
if(*temp2 >= 3)
{
*temp1 = *temp2;
temp1++;
temp2++;
}
else
{
n2--; //the number of elements left in the array is denoted by n2
temp2++;
}
}
}
Nested loops give you O(n2) complexity, and non-obvious code.
Better use std::remove_if:
int array[5] = {4, 2, 3, 5, 1};
int number = 3;
remove_if( begin( array ), end( array ), [=]( int x ) { return x>number; } );
Disclaimer: code untouched by compiler's hands.
Try this code. You should not decrease number at each step. Also, the second loop should start at i and stop at the end of array:
int array[5] = {4, 2, 3, 5, 1};
int number = 3;
for (int i = 0; i < number; i++)
{
if (array[i] > number)
{
for (int j = i; j < 5; j++)
{
array[j] = array[j + 1];
}
}
}
Here's a more compact and idiomatic (that's how I view it anyway) way to remove items from an array:
#include <iostream>
#include <algorithm>
#include <iterator>
int main()
{
int array[] = {4, 2, 3, 5, 1};
int* begin = array;
int* end = begin + sizeof(array)/sizeof(array[0]);
int number = 3;
end = std::remove_if(begin, end, [&number](int v) {return v > number;});
std::copy(begin, end, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}
Just for comparison, here's a version using std::vector:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
int main()
{
std::vector<int> array = {4, 2, 3, 5, 1};
int number = 3;
auto end = std::remove_if(array.begin(), array.end(), [&number](int v) {return v > number;});
std::copy(array.begin(), end, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}
As an alternative, if you want to keep your items, but denote what will be at some later time, "removed", the algorithm that can be used is stable_partition:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <functional>
int main()
{
int vValues[] = {4,2,3,5,1};
// partition the values on left and right. The left side will have values
// <= 3, and on right >3. The return value is the partition point.
int *p = std::stable_partition(vValues, vValues + 5,
std::bind2nd(std::less_equal<int>(), 3));
// display information
std::cout << "Partition is located at vValues[" << std::distance(vValues, p) << "]\n";
std::copy(vValues, vValues + 5, std::ostream_iterator<int>(std::cout, " "));
}
Output:
Partition is located at vValues[3]
2 3 1 4 5
You will see that 2,3,1 are on the left of partition p, and 4,5 are on the right of the partition p. So the "removed" items start at where p points to. The std::partition ensures the elements are still in their relative order when done.
I created my own example, hope this helps people as a reference:
// Removing an element from the array. Thus, shifting to the left.
void remove(){
int a[] = {1, 2, 3, 4, 5, 6};
int size = sizeof(a)/sizeof(int); // gives the size
for(int i = 0; i < size; i++){
cout << "Value: " << a[i] << endl;
}
int index = 2; // desired index to be removed
for(int i = 0; i < size; i++){
if(i == index){
for(int j = i; j < size; j++){
a[j] = a[j+1];
}
}
}
size--; // decrease the size of the array
cout << "\nTesting output: " << endl;
for(int i = 0; i < size; i++){
cout << "Value: " << a[i] << endl;
}
}
int main(){
remove();
return 0;
}

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;
}
}