Sort vector by even and odd indices. c++ - 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.

Related

access to iterator in lambda function of an algorithm cause me segmentation fault

I need to sort a table by column. My tables are represents by a single vector.
example :
col_name A B C
vector : 1 2 3 6 5 4 7 8 9
that give me the table :
A B C
1 6 7
2 5 8
3 4 9
After a sort on column B , I need to obtain :
A B C
3 4 9
2 5 8
1 6 7
my code :
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
int main()
{
std::vector<std::string> vec = {"1","8","1","2","3","2","3",
"5","5","2","5","6","5","6",
"9","3","3","4","8","3","9"};
std::vector<std::string> rec = {"1","1","8","2","2","3","3",
"2","5","5","5","5","6","6",
"3","9","3","4","3","8","9"};
int size = 7;
int col_idx = 1;
for(int i = 0; i<3;++i)
{
if(i==col_idx)
continue;
std::sort(vec.begin() + i*size, vec.begin() + (i+1)*size,
[col_idx, size, i](std::string& s1,std::string& s2)
{
std::cout << s1 << " "
<< s2 << " "
<< *(&s1 +(col_idx - i)*size) << " "
<< *(&s2 +(col_idx - i)*size) << " "
<< (*(&s1 +(col_idx - i)*size) < *(&s2 +(col_idx - i)*size)) << std::endl;
return *(&s1 +(col_idx - i)*size) < *(&s2 +(col_idx - i)*size);
});
}
std::sort(vec.begin() + col_idx*size, vec.begin() + (col_idx+1)*size);
}
assert(vec==res);
I have a segmentation fault error : only the first line appear from the cout.
Honestly, your approach looks rather complicated to me. Most of its complexity is due to the fact that you have rows in your code but they are present only implicitly. Making stuff explicit in code not only helps to increase readability but also makes code easier to write.
Lets say you use std::array<std::string,3> for rows, then your code could be as leightweight as this:
#include <vector>
#include <array>
#include <algorithm>
#include <iostream>
int main() {
using row_t = std::array<std::string,3>;
std::vector<row_t> vec = { {"1","8","1"},{"2","3","2"},{"3","5","5"},{"2","5","6"}};
std::sort(vec.begin(),vec.end(),[](const row_t& a, const row_t& b) { return a[2] < b[2]; });
for (const auto& row : vec) {
for (const auto& e : row) std::cout << e << " ";
std::cout << '\n';
}
}
Output:
1 8 1
2 3 2
3 5 5
2 5 6
Ok, that's probably a good approch for this problem, and maybe it's what should I do, but I can't pass 2 months to change all the code ...
You could have made the requirements more clear in the question. I think if you have 10k lines of code that depend on this particular issue using a flat vector, when a different data structure would be more appropriate, then you have a bigger problem than how to sort rows. Anyhow...
Using a flat std::vector is usually not a bad idea. What I miss from your code is something along the line of
template <int stride>
std::string& access_at(std::vector<std::string>& vec,size_t row,size_t col) {
return vec[ row * stride + col ];
}
template <int stride>
const std::string& access_at(const std::vector<std::string>& vec,size_t row,size_t col) {
return vec[ row * stride + col ];
}
That lets you iterate the table like this:
for (size_t i=0;i < vec.size()/3;++i) {
for (size_t j=0;j<3;++j) {
std::cout << access_at<3>(vec,i,j) << " ";
}
std::cout << '\n';
}
Next I am going to shamelessly steal and modify code from this answer. The basic idea is to sort a vector of indices instead of sorting the vector directly:
using index_t = std::vector<size_t>;
template <int stride>
index_t make_sorted_index(const std::vector<std::string>& values,size_t col) {
index_t index(values.size() / stride);
std::iota(index.begin(), index.end(), 0);
std::sort(index.begin(),
index.end(),
[&values,&col](size_t a, size_t b) {
return access_at<stride>(values,a,col) < access_at<stride>(values,b,col);
}
);
return index;
}
Once you have that, the loop to print the sorted table need only a minor modification:
for (size_t i=0;i < vec.size()/3;++i) {
for (size_t j=0;j<3;++j) {
std::cout << access_at<3>(vec,index[i],j) << " ";
}
std::cout << '\n';
}
Putting everything together:
#include <vector>
#include <numeric>
#include <algorithm>
#include <iostream>
template <int stride>
std::string& access_at(std::vector<std::string>& vec,size_t row,size_t col) { return vec[ row * stride + col ]; }
template <int stride>
const std::string& access_at(const std::vector<std::string>& vec,size_t row,size_t col) { return vec[ row * stride + col ]; }
using index_t = std::vector<size_t>;
template <int stride>
index_t make_sorted_index(const std::vector<std::string>& values,size_t col) {
index_t index(values.size() / stride);
std::iota(index.begin(), index.end(), 0);
std::sort(index.begin(),
index.end(),
[&values,&col](size_t a, size_t b) { return access_at<stride>(values,a,col) < access_at<stride>(values,b,col); }
);
return index;
}
int main() {
std::vector<std::string> vec = { "1","8","1","2","3","2","3","5","5","2","5","6"};
for (size_t i=0;i < vec.size()/3;++i) {
for (size_t j=0;j<3;++j) {
std::cout << access_at<3>(vec,i,j) << " ";
}
std::cout << '\n';
}
std::cout << '\n';
auto index = make_sorted_index<3>(vec,1);
for (size_t i=0;i < vec.size()/3;++i) {
for (size_t j=0;j<3;++j) {
std::cout << access_at<3>(vec,index[i],j) << " ";
}
std::cout << '\n';
}
}
With output:
1 8 1
2 3 2
3 5 5
2 5 6
2 3 2
3 5 5
2 5 6
1 8 1
I'll leave it to you to actually copy the vector to get the sorted one, if you really need that.
PS: In the first version above I sorted with respect to column C, the last part sorts with respect to B as requested.
PPS: I still dont understand your code. I don't understand why you have std::cout inside the predicate and to be honest I have no clue how your call to sort is supposed to achieve what you want.

A vector as a patchwork of two other vectors

Subset a vector
Below is the benchmark of two different solutions to subset a vector
#include <vector>
#include <iostream>
#include <iomanip>
#include <sys/time.h>
using namespace std;
int main()
{
struct timeval timeStart,
timeEnd;
// Build the vector 'whole' to subset
vector<int> whole;
for (int i = 0 ; i < 10000000 ; i++)
    {
whole.push_back(i);
}
// Solution 1 - Use a for loops
gettimeofday(&timeStart, NULL);
vector<int> subset1;
subset1.reserve(9123000 - 1200);
for (int i = 1200 ; i < 9123000 ; i++)
{
subset1.push_back(i);
}
gettimeofday(&timeEnd, NULL);
cout << "Solution 1 took " << ((timeEnd.tv_sec - timeStart.tv_sec) * 1000000 + timeEnd.tv_usec - timeStart.tv_usec) << " us" << endl;
// Solution 2 - Use iterators and constructor
gettimeofday(&timeStart, NULL);
vector<int>::iterator first = whole.begin() + 1200;
vector<int>::iterator last = whole.begin() + 9123000;
vector<int> subset2(first, last);
gettimeofday(&timeEnd, NULL);
cout << "Solution 2 took " << ((timeEnd.tv_sec - timeStart.tv_sec) * 1000000 + timeEnd.tv_usec - timeStart.tv_usec) << " us" << endl;
}
On my old laptop, it outputs
Solution 1 took 243564 us
Solution 2 took 164220 us
Clearly solution 2 is faster.
Make a patchwork of two vectors
I would like to create a vector as a patchwork of two different vectors of the same size. The vector starts as one and then takes the value of the other and back and forth. I guess I don't fully understand how to copy values to a vector by using iterator pointing to elements in another vector. The only implementation I can think of requires using an analogous to solution 1 above. Something like...
#include <vector>
#include <iostream>
#include <cmath>
#include <iomanip>
#include <sys/time.h>
#include <limits.h>
using namespace std;
int main()
{
// input
vector<int> breakpoints = {2, 5, 7, INT_MAX};
vector<int> v1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
vector<int> v2 = { 10, 20, 30, 40, 50, 60, 70, 80, 90 };
// Create output
vector<int> ExpectedOutput;
ExpectedOutput.reserve(v1.size());
int origin = 0;
int breakpoints_index = 0;
for (int i = 0 ; i < v1.size() ; i++)
{
if (origin)
{
ExpectedOutput.push_back(v1[i]);
} else
{
ExpectedOutput.push_back(v2[i]);
}
if (breakpoints[breakpoints_index] == i)
{
origin = !origin;
breakpoints_index++;
}
}
// print output
cout << "output: ";
for (int i = 0 ; i < ExpectedOutput.size() ; i++)
{
cout << ExpectedOutput[i] << " ";
}
cout << endl;
return 0;
}
which outputs
output: 10 20 30 4 5 6 70 80 9
It feels like there must be a better solution such as something analogous to Solution 2 from above. Is there a faster solution?
Repeating push_back() means that every time around the loop, a check is being performed to ensure capacity() is large enough (if not, then more space must be reserved). When you copy a whole range, only one capacity() check needs to be done.
You can still be a bit smarter with your interleaving by copying chunks. Here's the very basic idea:
int from = 0;
for( int b : breakpoints )
{
std::swap( v1, v2 );
int to = 1 + std::min( b, static_cast<int>( v1.size() ) - 1 );
ExpectedOutput.insert( ExpectedOutput.end(), v1.begin() + from, v1.begin() + to );
from = to;
}
For the sake of brevity, this code actually swaps v1 and v2 and so always operates on v1. I did the swap before the insert, to emulate the logic in your code (which is acting on v2 first). You can do this in a non-modifying way instead if you want.
Of course, you can see a bit more is going on in this code. It would only make sense if you have considerably fewer breakpoints than values. Note that it also assumes v1 and v2 are the same length.

Finding if 1 vector is included in 2nd vector

I need to write a program that finds out if one of the 2 vector is included in another one.
The program works like this.
1 - Gets the m and n values from input.txt (1st row)
2 - Resizes verctorM and vectorN to m and n, then fills them with numbers from input.txt (2nd row for vectorM, 3rd row for vectorN)
3 - After filling, the program should find out wich one of the vectors has the fewest "characters" by comparing n and m
4 - The program gets the first "character" of "small" vector and start to compare it with the "characters" of "big" vector ()
5 - When the statemant vectorN[i] = vectorM[0] is correct, the program compares the next "characters" if every "character" of "small" vector is in the "big" vector, program output 1, if not continues to compare with 1st "caracter" of "smal" vector, if "small" vector is not included in "big" vector, program outputs 0
Edit - the numbers must be in same order as written in input.txt
Here is the code that I ended up with
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
int main() {
int m;
int n;
bool y = false;
vector<int> vectorM;
vector<int> vectorN;
ifstream file1;
file1.open("input.txt");
file1 >> m;
file1 >> n;
vectorM.resize(m);
vectorN.resize(n);
for (int i = 0; i < m; i++){
file1 >> vectorM[i];
}
for (int i = 0; i < n; i++){
file1 >> vectorN[i];
}
//this is the part that I need help with
ofstream file2;
file2.open("output.txt");
if (y == false)
file2 << 0;
else
file2 << 1;
}
What's the efficent way to compare the "characters" ??
Example, if in input.txt
4 3
1 2 3 2
1 2 3
Program outputs 1, because 1 2 3 is in 1 2 3 2, but if
2 3
1 2
2 3 1
Program outputs 0
I think you're asking if a contiguous subsequence can be found inside another range of values. The standard library std::search algorithm does just that.
#include <algorithm>
#include <iostream>
#include <vector>
bool included(const std::vector<int>& seq, const std::vector<int>& sub)
{
return std::search(seq.begin(), seq.end(), sub.begin(), sub.end()) != seq.end();
}
int main()
{
auto v1 = std::vector<int>{ 1,2,3,2 };
auto v2 = std::vector<int>{ 1,2,3 };
std::cout << std::boolalpha << included(v1, v2) << '\n';
auto v3 = std::vector<int>{ 1,2 };
auto v4 = std::vector<int>{ 2,3,1 };
std::cout << included(v3, v4) << '\n';
}
Demo on ideone.com
Note: I stole Jarod42's function name and coincoin's test data.

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.

Smarter looping over permutations

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