Smarter looping over permutations - c++

I've got a 3 by 3 grid of boolean values, and I'm interested in the number of ways I can have exactly three "living" cells (there's 56 permutations, by my count). Rotational symmetries don't matter, but the living cells are indistinguishable from each other.
Assuming that I'm indexing the values in the grid relative to the centroid:
-------------------
|-1,-1| 0,-1| 1,-1|
-------------------
|-1,0 | | 1,0 |
-------------------
|-1,1 | 0,1 | 1,1 |
-------------------
is there a nice loop that I could use to calculate the 56 permutations? (I've just finished typing it all out, and I'd love to know if I could have been slightly smarter).
I'm using C++, but a basic algorithm would be wonderful in any language or pseudo-language, if it's clear.

You can use next_permutation.
For example, assume string each character in x below represents the a cell in the grid (except centroid cell) starting at top left and going to bottom right. You could run this code to find all the possible arrangements, and inside the loop, string x will represent a possible arrangement, where 1 is a live cell, and 0 is a dead one.
int main() {
string x = "00000111";
int cnt = 0;
do {
++cnt;
// do something useful with this configuration...
} while(next_permutation(x.begin(),x.end()));
cout<<cnt<<endl;
return 0;
}

Try this procedure from Wikipedia.
The following algorithm generates the next permutation lexicographically after a given permutation. It changes the given permutation in-place.
Find the largest index k such that a[k] < a[k + 1]. If no such index exists, the permutation is the last permutation.
Find the largest index l such that a[k] < a[l]. Since k + 1 is such an index, l is well defined and satisfies k < l.
Swap a[k] with a[l].
Reverse the sequence from a[k + 1] up to and including the final element a[n].

you could use this method:
assume you represent your grid with an array, where your elements are
[(-1,-1), (0,-1),(1,-1)...]
and so on, you basically take element in the first line, then second line, then third line.
So now, you just have to take all the available numbers you have, that is to say:
[1,1,1,0,0,0,0,0,0]
as you said you only want 3 living cells.
now that we decided wha tdifferent strings mean, you can simply take a code which performs permutation, like the xcellnt one at this link How To Generate Permutation In C?
hich does exactly what you want, or any ohte equivalent code like std::next_permutation which is in the algorithm library.

Do you prefer "smarter" looping or "saner"?
//c++ --std=c++11 test.cc
#include <iostream>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <utility>
using std::string;
using std::list;
using std::vector;
const string show[8] = { "(-1,-1)","( 0,-1)","( 1,-1)"
, "(-1, 0)", "( 1, 0)"
, "(-1, 1)","( 0, 1)","( 1, 1)"
};
auto permutations_of_living_cells =
[] (int number_of_living_cells) -> list<vector<string>>
{
typedef list<vector<string>> (*recT)( void*
, int
, int
, vector<string> &&
, list<vector<string>> &&
);
recT rec = []( void*r
, int n
, int i
, vector<string> && prefix
, list<vector<string>> && l
) -> list<vector<string>>
{
if( n==0 )
{
l.push_back(std::move(prefix));
return std::move(l);
}
if( i>8-n ) return std::move(l);
vector<string> psi(prefix);
psi.push_back(show[i]);
return ((recT)r)(r,n ,i+1,std::move(prefix),
((recT)r)(r,n-1,i+1,std::move(psi ),
std::move(l)
)
);
};
return rec( (void*)rec
, number_of_living_cells
, 0
, vector<string>()
, list<vector<string>>()
);
};
template<class T>
std::ostream& operator<<( std::ostream & out,const vector<T> & v )
{
if( v.empty() ) return out << "[]";
out << "[ " << *v.begin();
std::for_each( v.begin()+1, v.end(), [&](T x){out<<", "<<x;} );
return out << " ]";
}
int main()
{
for( auto v : permutations_of_living_cells(3) )
std::cout << v << "\n";
std::cout << std::flush;
return 0;
}

Related

Finding smallest number >= x not present in the given sorted array

I am having difficulty writing a modified binary search algorithm that returns the smallest number greater than or equal to X which is not present in the sorted array.
For example, if the array is {1,2,3,5,6} and x = 2 then answer is 4. Please guide me how to write the binary search for this. I have to answer this in O(log n) time for each x. Since I am taking this array as input which will initially take linear time, you may do some kind of preprocessing on the array initially if you want.
x is also taken as input and may or may not be present in the array.
The input array may have repeating elements.
My input numbers can be in the range [0,10^9] and hence first putting all the missing values in the array is not feasible because of space constraints.
Also, you can do preprocessing which takes O(n) time since you are taking the array as input in linear time. After that, there will be let us say 10^6 queries of X, which you have to answer, each in O(log n) time
If I understand correctly, you are allowed to do any kind of preprocessing and only finding the result for different x must be O(log n). If thats the case finding the result after preprocessing isn't a big deal. O(log n) search algorithms do exist. Good candidates are std::binary_search or std::lower_bound.
A very naive approach is to prepare a vector with all missing elements and then std::lower_bound on that:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> input{1,2,3,5,6,10,12};
std::vector<int> missing_elements{4,7,8,9,11};
int x = 2;
auto it = std::lower_bound(missing_elements.begin(),missing_elements.end(),x);
std::cout << *it << "\n";
}
Populating missing_elements can be done in O(1). However, a missing_elements with a size of the order of 10^9 is of course not feasible. Also this approach is extremely wasteful for input like [1,100000000] (not in terms of time complexity, but in terms of runtime and memory usage).
An idea put up by Jarod42 in a comment is to prepare a vector of segments and then std::lower_bound on that. First assuming preprocessing has already been done:
#include <iostream>
#include <vector>
#include <algorithm>
int find_first_missing(const std::vector<std::pair<int,int>>& segments,int x){
std::pair<int,int> p{x,x};
auto it = std::lower_bound(segments.begin(),segments.end(),p,[](auto a,auto b){
return a.second < b.second;
});
if (it == segments.end()) return x;
if (it->first > x) return x;
return it->second+1;
}
int main() {
std::vector<int> input{1,2,3,5,6,10,12};
std::vector<std::pair<int,int>> segments{{1,3},{5,6},{10,10},{12,12}};
for (int x=0; x<13;++x) std::cout << x << " -> " << find_first_missing(segments,x) << "\n";
}
Output:
0 -> 0
1 -> 4
2 -> 4
3 -> 4
4 -> 4
5 -> 7
6 -> 7
7 -> 7
8 -> 8
9 -> 9
10 -> 11
11 -> 11
12 -> 13
Because input is sorted, and segments is sorted, we can use a custom comparator that only compares the end of the segment. The vector of segments is also sorted with respect to that comparator. The call to lower_bound returns an iterator to the segment where either x is inside or x is lower than the segment, hence if (it->first > x) return x; otherwise we know that it->second+1 is the next missing number.
Now it is only left to create the vector of segments:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cassert>
std::vector<std::pair<int,int>> segment(const std::vector<int>& input){
std::vector<std::pair<int,int>> result;
if (input.size() == 0) return result;
int current_start = input[0];
for (int i=1;i<input.size();++i){
if (input[i-1] == input[i] || input[i-1]+1 == input[i]) continue;
result.push_back({current_start,input[i-1]});
current_start = input[i];
}
result.push_back({current_start,input.back()});
return result;
}
int main() {
std::vector<int> input{1,2,3,5,6,10,12};
std::vector<std::pair<int,int>> expected{{1,3},{5,6},{10,10},{12,12}};
auto result = segment(input);
for (const auto& e : result){
std::cout << e.first << " " << e.second << "\n";
}
assert(expected == result);
}
If x is not present in the array then return x.
If x is present, say it's at position l. Also, let's denote missing(i) to be the number of elements missing to the left of i. In a 1-indexed array, this equals A[i]-i. Then keep moving right from l until missing(i) - missing(l) = 0. You can use modified binary search for this. Suppose p is the position of the last element where missing(p) - missing(l) = 0 then A[p]+1 is the first missing number greater than x.
Take a look on this:
#include <iostream>
#include <vector>
using namespace std;
int greaterValue(const vector<int>& elements, int x){
int low = 0,
high = elements.size() -1,
answer = x + 1;
while (low <= high) {
int mid = (low + high) / 2;
if (elements[mid] <= answer) {
if (elements[mid] == answer) {
answer++;
high = elements.size() - 1;
}
low = mid + 1;
}
else {
high = mid - 1;
}
}
return answer;
}
int main() {
vector<int> elements = { 1, 2, 3, 5, 6 };
int x = 2;
int result = greaterValue(elements, x);
cout << "The element is: " << result;
return 0;
}
Test:
{ 1, 2, 3, 5, 6 }
Result:
The element is: 4
Time complexity:
O(log(n))

Vector custom sum

I need to identify the position of a variable from an integer array who has the following properties:
the sum of elements before this variable is equal with the sum of elements after this variable
if the variable doesn't exist, i will show a message.
For example, if x = {1,2,4,2,1}, the result is 4 with position 2, because 1 + 2 == 2 + 1.
Any suggestions? In this example it's easy
if((x[0]+x[1])==(x[3]+x[4]))
print position 2
But for n variables?
There are several ways to do this:
Brute force - n/2 passes:
Loop through the array.
For each element calculate the sum before and after that element.
If they match you found the element.
If the sum before becomes larger than the sum after, stop processing - no match found.
This is not really efficient for larger arrays.
1.5 passes:
Calculate the sum of all elements.
Divide that sum by 2 (half_sum).
Start summing the elements again from the beginning until you reach half_sum.
Check if you found a valid element or not.
Single pass (positive numbers only):
Keep two running sums: one from the beginning (sum1) and one from the end (sum2).
Set sum1 = first element and sum2 = last element.
Check for the smallest of the two and add the next/previous element to that.
Loop until the positions meet and check if the element is a valid result.
For each method you'll have to do a litlle check first to see if the array is not too small.
Special cases to consider:
Empty array: return false
Array with 1 element: return element
Array with 2 nonzero elements: return false
What with all zero's, or groups of zero's in the middle? (see Deduplicator's comment)
Negative elements: single pass version will not work here (see Cris Luengo's comment)
Negative elements in general: not reliable, consider +3 +1 -1 +1 -1 +3 +1 (see Deduplicator's comment)
Here is the O(n) solution.
Keep summing in in one variable from array beginning(left_sum) and keep deducing from the sum of elements except the first one using another(right_sum). When both becomes equal break the loop and print. Otherwise, show your msg.
#include <iostream>
#include <vector>
#include <numeric>
#include <cstddef>
int main()
{
std::vector<int> vec {1,2,4,2,1};
int left_sum = 0;
int right_sum = std::accumulate(vec.cbegin()+1, vec.cend(), 0);
bool Okay = false;
std::size_t index = 1; // start from index 1 until n-1
for( ; index < vec.size() - 1; ++index)
{
left_sum += vec[index-1];
right_sum -= vec[index];
if(left_sum == right_sum)
{
Okay = true;
break;
}
// in the case of array of positive integers
// if(left_sum > right_sum) break;
}
(Okay) ? std::cout << vec[index] << " " << index << std::endl: std::cout << "No such case!\n";
return 0;
}
Thanks for answers. I finally managed it. I used 3 for loops, and s0 is for sum before the element, and s1 is the sum after the element.
for(i=0;i<n;i++)
{s1=0;
s0=0;
for(int j=0;j<i-1;j++)
s0=s0+v[j];
for(int k=i;k<n;k++)
s1=s1+v[k];
if(s0==s1)
{cout<<endl<<"Position i="<<i;
x++;}
}
if(x==0)
cout<<"doesnt exist";
Well, do it in two steps:
Sum all elements.
From first to last:
If the sum equals the current element, success!
Subtract it twice from the sum (once for no longer being on the right, once for being on the left).
Use standard algorithms and range-for, and it's easily written:
auto first_balanced(std::span<const int> x) noexcept {
auto balance = std::accumulate(begin(x), end(x), 0LL);
for (auto&& n : x) {
if (balance == n)
return &n;
balance -= 2 * n;
}
return end(x);
}
It's just looping. You need to sum the elements before and after each index and just compare these two sums:
#include <iostream>
#include <vector>
#include <numeric>
int main() {
std::vector<int> x = {1, 2, 4, 2, 1};
for ( unsigned idx = 0; idx < x.size(); ++idx )
if ( std::accumulate(x.begin(), x.begin() + idx, 0) == std::accumulate(x.begin() + idx + 1, x.end(), 0) )
std::cout << idx << std::endl;
return 0;
}
Trying to build a solution out of std::algorithm,
n+lg n instead of n+~n/2
Warning untested code.
bool HasHalfSum(int& atIndex, const std::vector<int>& v) {
std::vector<int> sum;
sum.reserve(v.size);
std::partial_sum(v.begin(), v.end(), std::back_iterator(sum));
// 1,3,7,9,10
int half = sum.back() / 2; // 5
auto found = std::lower_bound(sum.begin(), sum.end(), half);
if (found != sum.begin() && std::prev(found) == sum.back() - *found) {
index = std::distance(sum.begin(), found);
return true;
}
return false;
}

Sort vector by even and odd indices. c++

Is there a one liner (or a simple loop-free) solution to sort a vector by its even and odd indices?
Example:
long entries[] = {0,1,2,10,11}; // indices 0 1 2 3 4
std::vector<long> vExample(entries, entries + sizeof(entries) / sizeof(long) );
vExample.sortEvenOdd(vExample.begin(),vExample.end()); // magic one liner I wish existed...
for (int i = 0; i < vExample.size(); i++)
{
std::cout << vExample[i] << " ";
}
Now I'd like to have the following output:
0 2 11 1 10 // corresponding to indices 0 2 4 1 3
I tried to do a real one liner:
std::stable_partition(std::begin(input), std::end(input),
[&input](int const& a){return 0==((&a-&input[0])%2);});
And here is the full program:
#include <algorithm>
#include <iostream>
#include <vector>
int main() {
std::vector<int> input {0,1,2,10,11};
std::stable_partition(std::begin(input), std::end(input),
[&input](int const& a){return 0==((&a-&input[0])%2);});
for (auto v : input)
std::cout << v << " ";
}
Ok I know, it works for the sole reason that vector uses a contiguous array of items and the whole thing is dirty... But for that's a one liner as asked by the OP and it doesn't require anything extra like boost...
This is not one liner but pretty close:
long entries[] = {0,1,2,10,11}; // indices 0 1 2 3 4
std::vector<long> vExample;
for( bool flag : { true, false } ) {
auto cond = [&flag]( long ) { flag = !flag; return !flag; };
std::copy_if( std::begin( entries ), std::end( entries ), std::back_inserter( vExample ), cond );
}
If you can use Boost, this is pretty concise:
#include <boost/range/adaptor/strided.hpp>
#include <boost/range/adaptor/sliced.hpp>
#include <boost/range/algorithm_ext/push_back.hpp>
#include <iostream>
#include <vector>
int main() {
using namespace boost::adaptors;
std::vector<int> input {0,1,2,10,11};
std::vector<int> partitioned;
boost::push_back(partitioned, input | strided(2));
boost::push_back(partitioned, input | sliced(1, input.size()) | strided(2));
for (auto v : partitioned)
std::cout << v << " ";
}
You can of course wrap that in a function to get a one liner in the calling code. Live
I don't like the messy business of fiddling with the addresses that the accepted answer of #fjardon proposes. #Slava's suggestion is much better and combined with the OP's code gives something that works quite well:
int main() {
std::vector<int> vals {0,2,3,-3,8,-5,7,8};
bool flag = true;
std::stable_partition(begin(vals), end(vals), [&flag] (auto el) mutable
{
// toggle flag, return previous value
flag = !flag; return !flag;
});
for (auto v : vals)
std::cout << v << " ";
}
Output: 0 3 8 7 2 -3 -5 8
What you need is stable_partition. Define a predicate which checks whether the index is even using modulo 2, and you are good to go.

Iterate through different subset of size k

I have an array of n integers (not necessarily distinct!) and I would like to iterate over all subsets of size k. However I'd like to exclude all duplicate subsets.
e.g.
array = {1,2,2,3,3,3,3}, n = 7, k = 2
then the subsets I want to iterate over (each once) are:
{1,2},{1,3},{2,2},{2,3},{3,3}
What is an efficient algorithm for doing this?
Is a recursive approach the most efficient/elegant?
In case you have a language-specific answer, I'm using C++.
The same (or almost the same) algorithm which is used to generated combinations of a set of unique values in lexicographical order can be used to generate combinations of a multiset in lexicographical order. Doing it this way avoids the necessity to deduplicate, which is horribly expensive, and also avoids the necessity of maintaining all the generated combinations. It does require that the original list of values be sorted.
The following simple implementation finds the next k-combination of a multiset of n values in average (and worst-case) time O(n). It expects two ranges: the first range is a sorted k-combination, and the second range is the sorted multiset. (If either range is unsorted or the values in first range do not constitute a sub(multi)set of the second range, then the behaviour is undefined; no sanity checks are made.)
Only the end iterator from the second range is actually used, but I thought that made the calling convention a bit odd.
template<typename BidiIter, typename CBidiIter,
typename Compare = std::less<typename BidiIter::value_type>>
int next_comb(BidiIter first, BidiIter last,
CBidiIter /* first_value */, CBidiIter last_value,
Compare comp=Compare()) {
/* 1. Find the rightmost value which could be advanced, if any */
auto p = last;
while (p != first && !comp(*(p - 1), *--last_value)) --p;
if (p == first) return false;
/* 2. Find the smallest value which is greater than the selected value */
for (--p; comp(*p, *(last_value - 1)); --last_value) { }
/* 3. Overwrite the suffix of the subset with the lexicographically smallest
* sequence starting with the new value */
while (p != last) *p++ = *last_value++;
return true;
}
It should be clear that steps 1 and 2 combined make at most O(n) comparisons, because each of the n values is used in at most one comparison. Step 3 copies at most O(k) values, and we know that k≤n.
This could be improved to O(k) in the case where no values are repeated, by maintaining the current combination as a container of iterators into the value list rather than actual values. This would also avoid copying values, at the cost of extra dereferences. If in addition we cache the function which associates each value iterator with an iterator to the first instance of next largest value, we could eliminate Step 2 and reduce the algorithm to O(k) even for repeated values. That might be worthwhile if there are a large number of repeats and comparisons are expensive.
Here's a simple use example:
std::vector<int> values = {1,2,2,3,3,3,3};
/* Since that's sorted, the first subset is just the first k values */
const int k = 2;
std::vector<int> subset{values.cbegin(), values.cbegin() + k};
/* Print each combination */
do {
for (auto const& v : subset) std::cout << v << ' ';
std::cout << '\n';
} while (next_comb(subset.begin(), subset.end(),
values.cbegin(), values.cend()));
Live on coliru
I like bit-twiddling for this problem. Sure, it limits you to only 32 elements in your vector, but it's still cool.
First, given a bit mask, determine the next bitmask permutation (source):
uint32_t next(uint32_t v) {
uint32_t t = v | (v - 1);
return (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));
}
Next, given a vector and a bitmask, give a new vector based on that mask:
std::vector<int> filter(const std::vector<int>& v, uint32_t mask) {
std::vector<int> res;
while (mask) {
res.push_back(v[__builtin_ctz(mask)]);
mask &= mask - 1;
}
return res;
}
And with that, we just need a loop:
std::set<std::vector<int>> get_subsets(const std::vector<int>& arr, uint32_t k) {
std::set<std::vector<int>> s;
uint32_t max = (1 << arr.size());
for (uint32_t v = (1 << k) - 1; v < max; v = next(v)) {
s.insert(filter(arr, v));
}
return s;
}
int main()
{
auto s = get_subsets({1, 2, 2, 3, 3, 3, 3}, 2);
std::cout << s.size() << std::endl; // prints 5
}
The basic idea of this solution is a function like next_permutation but which generates the next ascending sequence of "digits". Here called ascend_ordered.
template< class It >
auto ascend_ordered( const int n_digits, const It begin, const It end )
-> bool
{
using R_it = reverse_iterator< It >;
const R_it r_begin = R_it( end );
const R_it r_end = R_it( begin );
int max_digit = n_digits - 1;
for( R_it it = r_begin ; it != r_end; ++it )
{
if( *it < max_digit )
{
++*it;
const int n_further_items = it - r_begin;
for( It it2 = end - n_further_items; it2 != end; ++it2 )
{
*it2 = *(it2 - 1) + 1;
}
return true;
}
--max_digit;
}
return false;
}
Main program for the case at hand:
auto main() -> int
{
vector<int> a = {1,2,2,3,3,3,3};
assert( is_sorted( begin( a ), end( a ) ) );
const int k = 2;
const int n = a.size();
vector<int> indices( k );
iota( indices.begin(), indices.end(), 0 ); // Fill with 0, 1, 2 ...
set<vector<int>> encountered;
for( ;; )
{
vector<int> current;
for( int const i : indices ) { current.push_back( a[i] ); }
if( encountered.count( current ) == 0 )
{
cout << "Indices " << indices << " -> values " << current << endl;
encountered.insert( current );
}
if( not ascend_ordered( n, begin( indices ), end( indices ) ) )
{
break;
}
}
}
Supporting includes and i/o:
#include <algorithm>
using std::is_sorted;
#include <assert.h>
#include <iterator>
using std::reverse_iterator;
#include <iostream>
using std::ostream; using std::cout; using std::endl;
#include <numeric>
using std::iota;
#include <set>
using std::set;
#include <utility>
using std::begin; using std::end;
#include <vector>
using std::vector;
template< class Container, class Enable_if = typename Container::value_type >
auto operator<<( ostream& stream, const Container& c )
-> ostream&
{
stream << "{";
int n_items_outputted = 0;
for( const int x : c )
{
if( n_items_outputted >= 1 ) { stream << ", "; }
stream << x;
++n_items_outputted;
}
stream << "}";
return stream;
}
Unlike the previous answer, this is not as efficient and doesn't do anything as fancy as a lot of the bit twiddling. However it does not limit the size of your array or the size of the subset.
This solution uses std::next_permutation to generate the combinations, and takes advantage of std::set's uniqueness property.
#include <algorithm>
#include <vector>
#include <set>
#include <iostream>
#include <iterator>
using namespace std;
std::set<std::vector<int>> getSubsets(const std::vector<int>& vect, size_t numToChoose)
{
std::set<std::vector<int>> returnVal;
// return the whole thing if we want to
// choose everything
if (numToChoose >= vect.size())
{
returnVal.insert(vect);
return returnVal;
}
// set up bool vector for combination processing
std::vector<bool> bVect(vect.size() - numToChoose, false);
// stick the true values at the end of the vector
bVect.resize(bVect.size() + numToChoose, true);
// select where the ones are set in the bool vector and populate
// the combination vector
do
{
std::vector<int> combination;
for (size_t i = 0; i < bVect.size() && combination.size() <= numToChoose; ++i)
{
if (bVect[i])
combination.push_back(vect[i]);
}
// sort the combinations
std::sort(combination.begin(), combination.end());
// insert this new combination in the set
returnVal.insert(combination);
} while (next_permutation(bVect.begin(), bVect.end()));
return returnVal;
}
int main()
{
std::vector<int> myVect = {1,2,2,3,3,3,3};
// number to select
size_t numToSelect = 3;
// get the subsets
std::set<std::vector<int>> subSets = getSubsets(myVect, numToSelect);
// output the results
for_each(subSets.begin(), subSets.end(), [] (const vector<int>& v)
{ cout << "subset "; copy(v.begin(), v.end(), ostream_iterator<int>(cout, " ")); cout << "\n"; });
}
Live example: http://coliru.stacked-crooked.com/a/beb800809d78db1a
Basically we set up a bool vector and populate a vector with the values that correspond with the position of the true items in the bool vector. Then we sort and insert this into a set. The std::next_permutation shuffles the true values in the bool array around and we just repeat.
Admittedly, not as sophisticated and more than likely slower than the previous answer, but it should do the job.

next_permutation for combinations or subsets in powerset

Is there some equivalent library or function that will give me the next combination of a set of values like next_permutation in does for me?
Combinations: from Mark Nelson's article on the same topic we have next_combination http://marknelson.us/2002/03/01/next-permutation
Permutations: from STL we have std::next_permutation
template <typename Iterator>
inline bool next_combination(const Iterator first, Iterator k, const Iterator last)
{
if ((first == last) || (first == k) || (last == k))
return false;
Iterator itr1 = first;
Iterator itr2 = last;
++itr1;
if (last == itr1)
return false;
itr1 = last;
--itr1;
itr1 = k;
--itr2;
while (first != itr1)
{
if (*--itr1 < *itr2)
{
Iterator j = k;
while (!(*itr1 < *j)) ++j;
std::iter_swap(itr1,j);
++itr1;
++j;
itr2 = k;
std::rotate(itr1,j,last);
while (last != j)
{
++j;
++itr2;
}
std::rotate(k,itr2,last);
return true;
}
}
std::rotate(first,k,last);
return false;
}
I am not aware of one. The basic idea is to represent your elements as a bit array. So for example, you have the set S:
S = {a, b, c}
[i, j, k] // a is the first bit, b is the second bit, c is the third bit
To generate the Power Set of S(just generate all numbers that are of size == 3 bits by using the simple addition):
000 // {}
001 // {c}
010 // {b}
011 // {b, c}
100 // {a}
101 // {a, c}
110 // {a, b}
111 // {a, b, c}
All what you have to do is to find what bits are set, and to relate them to your set's elements.
On final note, there is one combination you can produce when you want all elements to be used and that combination is the set it self, because in combinations the order doesn't matter so for sure we are talking about a number of elements n where 0 <= n <= size(S)
I've used this library when I've needed to do this. It has an interface very similar to std::next_permutation so it will be easy to use if you've used that before.
Enumeration of the powerset (that is, all combinations of all sizes) can use an adaptation of the binary increment algorithm.
template< class I, class O > // I forward, O bidirectional iterator
O next_subset( I uni_first, I uni_last, // set universe in a range
O sub_first, O sub_last ) { // current subset in a range
std::pair< O, I > mis = std::mismatch( sub_first, sub_last, uni_first );
if ( mis.second == uni_last ) return sub_first; // finished cycle
O ret;
if ( mis.first == sub_first ) { // copy elements following mismatch
std::copy_backward( mis.first, sub_last, ++ (ret = sub_last) );
} else ret = std::copy( mis.first, sub_last, ++ O(sub_first) );
* sub_first = * mis.second; // add first element not yet in result
return ret; // return end of new subset. (Output range must accommodate.)
}
The requirement of a bidirectional iterator is unfortunate, and could be worked around.
I was going to make it handle identical elements (multisets), but I need to go to bed :v( .
Usage:
#include <iostream>
#include <vector>
using namespace std;
char const *fruits_a[] = { "apples", "beans", "cherries", "durian" };
vector< string > fruits( fruits_a, fruits_a + sizeof fruits_a/sizeof *fruits_a );
int main() {
vector< string > sub_fruits( fruits.size() );
vector< string >::iterator last_fruit = sub_fruits.begin();
while (
( last_fruit = next_subset( fruits.begin(), fruits.end(),
sub_fruits.begin(), last_fruit ) )
!= sub_fruits.begin() ) {
cerr << "size " << last_fruit - sub_fruits.begin() << ": ";
for ( vector<string>::iterator fit = sub_fruits.begin(); fit != last_fruit; ++ fit ) {
cerr << * fit << " ";
}
cerr << endl;
}
}
EDIT: Here is the version for multisets. The set doesn't have to be sorted but identical elements do have to be grouped together.
#include <iterator>
#include <algorithm>
#include <functional>
template< class I, class O > // I forward, O bidirectional iterator
I next_subset( I uni_first, I uni_last, // set universe in a range
O sub_first, O sub_last ) { // current subset in a range
std::pair< O, I > mis = std::mismatch( sub_first, sub_last, uni_first );
if ( mis.second == uni_last ) return sub_first; // finished cycle
typedef std::reverse_iterator<O> RO;
mis.first = std::find_if( RO(mis.first), RO(sub_first), std::bind1st(
std::not_equal_to< typename std::iterator_traits<O>::value_type >(),
* mis.second ) ).base(); // move mis.first before identical grouping
O ret;
if ( mis.first != sub_first ) { // copy elements after mismatch
ret = std::copy( mis.first, sub_last, ++ O(sub_first) );
} else std::copy_backward( mis.first, sub_last, ++ (ret = sub_last) );
* sub_first = * mis.second; // add first element not yet in result
return ret;
}
#include <vector>
#include <iostream>
using namespace std;
char const *fruits_a[] = { "apples", "apples", "beans", "beans", "cherries" };
vector< string > fruits( fruits_a, fruits_a + sizeof fruits_a/sizeof *fruits_a );
int main() {
vector< string > sub_fruits( fruits.size() );
vector< string >::iterator last_fruit = sub_fruits.begin();
while (
( last_fruit = next_subset( fruits.begin(), fruits.end(),
sub_fruits.begin(), last_fruit )
) != sub_fruits.begin() ) {
cerr << "size " << last_fruit - sub_fruits.begin() << ": ";
for ( vector<string>::iterator fit = sub_fruits.begin(); fit != last_fruit; ++ fit ) {
cerr << * fit << " ";
}
cerr << endl;
}
}
Output:
size 1: apples
size 2: apples apples
size 1: beans
size 2: apples beans
size 3: apples apples beans
size 2: beans beans
size 3: apples beans beans
size 4: apples apples beans beans
size 1: cherries
size 2: apples cherries
size 3: apples apples cherries
size 2: beans cherries
size 3: apples beans cherries
size 4: apples apples beans cherries
size 3: beans beans cherries
size 4: apples beans beans cherries
size 5: apples apples beans beans cherries
Googling for C++ "next_combination" turned up this.
search from "mid" backwards until you find an element that is smaller
than *(end - 1). This is the element
we should increment. Call this
"head_pos".
search from "end" backwards until you find the last element that is
still larger than *head_pos. Call it
"tail_pos".
swap head_pos and tail_pos. Re-order the elements from [head_pos + 1, mid[
and [tail_pos + 1, end[ in increasing
order.
In case You have no choice, but to implement Your own function maybe this horror can help a bit or maybe other horrors among answers to that question.
Algorithm to return all combinations of k elements from n
I wrote it some time ago and the full picture eludes me now :), but the basic idea is this:
You have the original set and current combination is a vector of iterators to the elements selected. To get the next combination, You scan your set from right to left looking for a "bubble". By "bubble" I mean one or more adjacent elements not selected. The "bubble" might be immediately at the right. Then, in Your combination, You exchange the first element at the left of the "bubble" and all other elements from the combination, that are to the right in the set, with a subset of adjacent elements that starts at the beginning of the "bubble".