#include <vector>
#include <algorithm>
struct for_each_unmirrored {
template<class datapoint, class function>
for_each_unmirrored(const std::vector<datapoint>& data, int num_values, function&& func) {
std::vector<unsigned> indexes;
indexes.reserve(num_values);
if (num_values)
for_each_unmirrored_helper(0, data.size(), num_values, data, func, indexes);
}
private:
template<class datapoint, class function>
void for_each_unmirrored_helper(unsigned minindex, unsigned maxindex, unsigned num_values, const std::vector<datapoint>& data, function& func, std::vector<unsigned>& indexes) {
if (minindex >= maxindex)
return;
//First is set, but not last
indexes.push_back(minindex);
if (num_values-1 > 0) {
for_each_mirrored_helper(minindex+1, maxindex-1, num_values-1, data, func, indexes);
//First and last are set
if (num_values-2 > 0) {
indexes.push_back(maxindex-1);
for_each_unmirrored_helper(minindex+1, maxindex-1, num_values-2, data, func, indexes);
indexes.pop_back();
}
} else
for_each_call_helper(data, func, indexes);
indexes.pop_back();
//neither first nor last are set
for_each_unmirrored_helper(minindex+1, maxindex-1, num_values, data, func, indexes);
}
template<class datapoint, class function>
void for_each_mirrored_helper(unsigned minindex, unsigned maxindex, unsigned num_values, const std::vector<datapoint>& data, function& func, std::vector<unsigned>& indexes) {
if (minindex >= maxindex)
return;
indexes.push_back(minindex);
for( ; indexes.back() < maxindex; ++indexes.back()) {
if (num_values>1)
for_each_mirrored_helper(indexes.back()+1, maxindex, num_values-1, data, func, indexes);
else
for_each_call_helper(data, func, indexes);
}
indexes.pop_back();
}
template<class datapoint, class function>
void for_each_call_helper(const std::vector<datapoint>& data, function& func, std::vector<unsigned>& indexes) {
static std::vector<unsigned> sorted_indexes;
sorted_indexes = indexes;
static std::vector<datapoint> call_data;
call_data.reserve(sorted_indexes.size());
call_data.clear();
std::sort(sorted_indexes.begin(), sorted_indexes.end());
for(unsigned i=0; i<sorted_indexes.size(); ++i)
call_data.push_back(data[sorted_indexes[i]]);
func(call_data);
}
};
#include <iostream>
#include <string>
struct printer {
void operator()(const std::vector<std::string>& data) {
for(unsigned i=0; i<data.size(); ++i)
std::cout << data[i] << ' ';
std::cout << '\n';
}
};
int main() {
std::vector<std::string> data;
data.push_back("A");
data.push_back("B");
data.push_back("C");
data.push_back("D");
data.push_back("E");
data.push_back("F");
for_each_unmirrored(data, 3, printer());
return 0;
}
/*expected output:
5 elements: A B C D E. pick 2 unique.
Results:
A B
A C
A D
A E
B C
B D
6 elements: A B C D E F. pick 2 unique.
Results:
A B
A C
A D
A E
A F
B C
B D
B E
C D
6 elements: A B C D E F. pick 3 unique.
Results:
A B C
A B D
A B E
A C D
A C E
A D E
A B F
A C F
B C D
B C E
*/
I2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPGFsZ29yaXRobT4KCnN0cnVjdCBmb3JfZWFjaF91bm1pcnJvcmVkIHsKCgl0ZW1wbGF0ZTxjbGFzcyBkYXRhcG9pbnQsIGNsYXNzIGZ1bmN0aW9uPgoJZm9yX2VhY2hfdW5taXJyb3JlZChjb25zdCBzdGQ6OnZlY3RvcjxkYXRhcG9pbnQ+JiBkYXRhLCBpbnQgbnVtX3ZhbHVlcywgZnVuY3Rpb24mJiBmdW5jKSB7CgkJc3RkOjp2ZWN0b3I8dW5zaWduZWQ+IGluZGV4ZXM7CgkJaW5kZXhlcy5yZXNlcnZlKG51bV92YWx1ZXMpOwoJCWlmIChudW1fdmFsdWVzKQoJCQlmb3JfZWFjaF91bm1pcnJvcmVkX2hlbHBlcigwLCBkYXRhLnNpemUoKSwgbnVtX3ZhbHVlcywgZGF0YSwgZnVuYywgaW5kZXhlcyk7Cgl9CnByaXZhdGU6Cgl0ZW1wbGF0ZTxjbGFzcyBkYXRhcG9pbnQsIGNsYXNzIGZ1bmN0aW9uPgoJdm9pZCBmb3JfZWFjaF91bm1pcnJvcmVkX2hlbHBlcih1bnNpZ25lZCBtaW5pbmRleCwgdW5zaWduZWQgbWF4aW5kZXgsIHVuc2lnbmVkIG51bV92YWx1ZXMsIGNvbnN0IHN0ZDo6dmVjdG9yPGRhdGFwb2ludD4mIGRhdGEsIGZ1bmN0aW9uJiBmdW5jLCBzdGQ6OnZlY3Rvcjx1bnNpZ25lZD4mIGluZGV4ZXMpIHsKCQlpZiAobWluaW5kZXggPj0gbWF4aW5kZXgpCgkJCXJldHVybjsKCQkvL0ZpcnN0IGlzIHNldCwgYnV0IG5vdCBsYXN0CgkJaW5kZXhlcy5wdXNoX2JhY2sobWluaW5kZXgpOwoJCWlmIChudW1fdmFsdWVzLTEgPiAwKSB7CgkJCWZvcl9lYWNoX21pcnJvcmVkX2hlbHBlcihtaW5pbmRleCsxLCBtYXhpbmRleC0xLCBudW1fdmFsdWVzLTEsIGRhdGEsIGZ1bmMsIGluZGV4ZXMpOwoJCQkvL0ZpcnN0IGFuZCBsYXN0IGFyZSBzZXQKCQkJaWYgKG51bV92YWx1ZXMtMiA+IDApIHsKCQkJCWluZGV4ZXMucHVzaF9iYWNrKG1heGluZGV4LTEpOwoJCQkJZm9yX2VhY2hfdW5taXJyb3JlZF9oZWxwZXIobWluaW5kZXgrMSwgbWF4aW5kZXgtMSwgbnVtX3ZhbHVlcy0yLCBkYXRhLCBmdW5jLCBpbmRleGVzKTsKCQkJaW5kZXhlcy5wb3BfYmFjaygpOwoJCQl9CgkJfSBlbHNlCgkJCWZvcl9lYWNoX2NhbGxfaGVscGVyKGRhdGEsIGZ1bmMsIGluZGV4ZXMpOwoJCWluZGV4ZXMucG9wX2JhY2soKTsKCQkvL25laXRoZXIgZmlyc3Qgbm9yIGxhc3QgYXJlIHNldAoJCWZvcl9lYWNoX3VubWlycm9yZWRfaGVscGVyKG1pbmluZGV4KzEsIG1heGluZGV4LTEsIG51bV92YWx1ZXMsIGRhdGEsIGZ1bmMsIGluZGV4ZXMpOwoJfQoKCXRlbXBsYXRlPGNsYXNzIGRhdGFwb2ludCwgY2xhc3MgZnVuY3Rpb24+Cgl2b2lkIGZvcl9lYWNoX21pcnJvcmVkX2hlbHBlcih1bnNpZ25lZCBtaW5pbmRleCwgdW5zaWduZWQgbWF4aW5kZXgsIHVuc2lnbmVkIG51bV92YWx1ZXMsIGNvbnN0IHN0ZDo6dmVjdG9yPGRhdGFwb2ludD4mIGRhdGEsIGZ1bmN0aW9uJiBmdW5jLCBzdGQ6OnZlY3Rvcjx1bnNpZ25lZD4mIGluZGV4ZXMpIHsKCQlpZiAobWluaW5kZXggPj0gbWF4aW5kZXgpCgkJCXJldHVybjsKCQlpbmRleGVzLnB1c2hfYmFjayhtaW5pbmRleCk7CgkJZm9yKCA7IGluZGV4ZXMuYmFjaygpIDwgbWF4aW5kZXg7ICsraW5kZXhlcy5iYWNrKCkpIHsKCQkJaWYgKG51bV92YWx1ZXM+MSkKCQkJCWZvcl9lYWNoX21pcnJvcmVkX2hlbHBlcihpbmRleGVzLmJhY2soKSsxLCBtYXhpbmRleCwgbnVtX3ZhbHVlcy0xLCBkYXRhLCBmdW5jLCBpbmRleGVzKTsKCQkJZWxzZQoJCQkJZm9yX2VhY2hfY2FsbF9oZWxwZXIoZGF0YSwgZnVuYywgaW5kZXhlcyk7CgkJfQoJCWluZGV4ZXMucG9wX2JhY2soKTsKCX0KCgl0ZW1wbGF0ZTxjbGFzcyBkYXRhcG9pbnQsIGNsYXNzIGZ1bmN0aW9uPgoJdm9pZCBmb3JfZWFjaF9jYWxsX2hlbHBlcihjb25zdCBzdGQ6OnZlY3RvcjxkYXRhcG9pbnQ+JiBkYXRhLCBmdW5jdGlvbiYgZnVuYywgc3RkOjp2ZWN0b3I8dW5zaWduZWQ+JiBpbmRleGVzKSB7CgkJc3RhdGljIHN0ZDo6dmVjdG9yPHVuc2lnbmVkPiBzb3J0ZWRfaW5kZXhlczsKCQlzb3J0ZWRfaW5kZXhlcyA9IGluZGV4ZXM7CgkJc3RhdGljIHN0ZDo6dmVjdG9yPGRhdGFwb2ludD4gY2FsbF9kYXRhOwoJCWNhbGxfZGF0YS5yZXNlcnZlKHNvcnRlZF9pbmRleGVzLnNpemUoKSk7CgkJY2FsbF9kYXRhLmNsZWFyKCk7CgoJCXN0ZDo6c29ydChzb3J0ZWRfaW5kZXhlcy5iZWdpbigpLCBzb3J0ZWRfaW5kZXhlcy5lbmQoKSk7CgkJZm9yKHVuc2lnbmVkIGk9MDsgaTxzb3J0ZWRfaW5kZXhlcy5zaXplKCk7ICsraSkKCQkJY2FsbF9kYXRhLnB1c2hfYmFjayhkYXRhW3NvcnRlZF9pbmRleGVzW2ldXSk7CgkJZnVuYyhjYWxsX2RhdGEpOwoJfQp9OwoKCgojaW5jbHVkZSA8aW9zdHJlYW0+CiNpbmNsdWRlIDxzdHJpbmc+CnN0cnVjdCBwcmludGVyIHsKICAgIHZvaWQgb3BlcmF0b3IoKShjb25zdCBzdGQ6OnZlY3RvcjxzdGQ6OnN0cmluZz4mIGRhdGEpIHsKICAgICAgICBmb3IodW5zaWduZWQgaT0wOyBpPGRhdGEuc2l6ZSgpOyArK2kpCiAgICAgICAgICAgIHN0ZDo6Y291dCA8PCBkYXRhW2ldIDw8ICcgJzsKICAgICAgICBzdGQ6OmNvdXQgPDwgJ1xuJzsKICAgIH0KfTsKCmludCBtYWluKCkgewogICAgc3RkOjp2ZWN0b3I8c3RkOjpzdHJpbmc+IGRhdGE7CglkYXRhLnB1c2hfYmFjaygiQSIpOwoJZGF0YS5wdXNoX2JhY2soIkIiKTsKCWRhdGEucHVzaF9iYWNrKCJDIik7CglkYXRhLnB1c2hfYmFjaygiRCIpOwoJZGF0YS5wdXNoX2JhY2soIkUiKTsKCWRhdGEucHVzaF9iYWNrKCJGIik7CiAgICBmb3JfZWFjaF91bm1pcnJvcmVkKGRhdGEsIDMsIHByaW50ZXIoKSk7CglyZXR1cm4gMDsKfQogICAgCi8qZXhwZWN0ZWQgb3V0cHV0Ogo1IGVsZW1lbnRzOiBBIEIgQyBEIEUuICBwaWNrIDIgdW5pcXVlLgpSZXN1bHRzOgpBIEIKQSBDCkEgRApBIEUKQiBDCkIgRAogCjYgZWxlbWVudHM6IEEgQiBDIEQgRSBGLiAgcGljayAyIHVuaXF1ZS4KUmVzdWx0czoKQSBCCkEgQwpBIEQKQSBFCkEgRgpCIEMKQiBECkIgRQpDIEQKIAogCjYgZWxlbWVudHM6IEEgQiBDIEQgRSBGLiAgcGljayAzIHVuaXF1ZS4KUmVzdWx0czoKQSBCIEMKQSBCIEQKQSBCIEUKQSBDIEQKQSBDIEUKQSBEIEUKQSBCIEYKQSBDIEYKQiBDIEQKQiBDIEUKKi8=