After adding a queue for a work pool, in which i put the jobs and get them with a unique_lock, i get memory leak errors, but i can't find where i am missing to delete.
Simple logic: i got a farm, it split the work, give them to threads, threads do the computation and push into the queue the results, then the emitter node split the job if needed and send it to the threads again.
I give you the actual code and i also post the error of -fsanitize=addres, anyway the code is runnable and you can try with your best profiling tool.
#include <iostream>
#include <unistd.h>
#include <typeinfo>
#include <chrono>
#include <thread>
#include <ff/ff.hpp>
#include <ff/pipeline.hpp>
#include <ff/farm.hpp>
#include <mutex>
#include <atomic>
#include <list>
#include <array>
#include <math.h>
#define UNASSIGNED 0
#define N 9
#define ERROR_PAIR std::make_pair(-1, -1)
using namespace std;
using namespace ff;
atomic<bool> solutionFound{false};
mutex mtx;
// Declaration for a tree node
struct Node {
array<unsigned char, N * N> grid;
vector<Node *> child;
};
vector<vector<Node *>> queueWork(0, vector<Node *>(0));
// Utility function to create a new tree node
Node *newNode(const array<unsigned char, N * N> &newGrid) {
Node *temp = new Node;
temp->grid = newGrid;
return temp;
}
void printGrid(const array<unsigned char, N * N> &grid) {
for (int row = 0; row < N; row++) {
if (row == 3 || row == 6) {
cout << "---------------------" << endl;
}
for (int col = 0; col < N; col++) {
if (col == 3 || col == 6) {
cout << "| ";
}
cout << (int)grid[row + col * N] << " ";
}
cout << endl;
}
}
bool canInsert(const int &val, const int &row_, const int &col_,
const array<unsigned char, N * N> &grid) {
// Check column
for (int row = 0; row < N; row++) {
if (grid[row + col_ * N] == val) return false;
}
// check row
for (int col = 0; col < N; col++) {
if (grid[row_ + col * N] == val) return false;
}
// check box
for (int row = 0; row < N; row++) {
for (int col = 0; col < N; col++) {
if (row / 3 == row_ / 3 &&
col / 3 == col_ / 3) { // they are in the same square 3x3
if ((grid[row + col * N] == val)) return false;
}
}
}
return true;
}
// vector<vector<int>> gridTest(9, vector<int>(9,0)); il vettore deve essere
// inizializzato, cosi. n = how many numbers you want to initialize the matrix
// with
void generateMatrix(const int &seed, const int &n,
array<unsigned char, N * N> &grid) {
srand(seed);
int i = 0;
while (i < n) {
int row = rand() % 9;
int col = rand() % 9;
int val = rand() % 9 + 1;
if (grid[row + col * N] == UNASSIGNED &&
canInsert(val, row, col, grid)) {
grid[row + col * N] = val;
i++;
}
}
return;
}
bool isSolution(
const array<unsigned char, N * N> &grid) // check if the sudoku is solved
{
char row_[9][N + 1] = {0};
char column_[9][N + 1] = {0};
char box[3][3][N + 1] = {0};
for (int row = 0; row < N; row++) {
for (int col = 0; col < N; col++) {
// mark the element in row column and box
row_[row][grid[row + col * N]] += 1;
column_[col][grid[row + col * N]] += 1;
box[row / 3][col / 3][grid[row + col * N]] += 1;
// if an element is already
// present in the hashmap
if (box[row / 3][col / 3][grid[row + col * N]] > 1 ||
column_[col][grid[row + col * N]] > 1 ||
row_[row][grid[row + col * N]] > 1)
return false;
}
}
return true;
}
pair<int, int> findCell(const array<unsigned char, N * N> &grid) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (grid[i + j * N] == UNASSIGNED) {
return make_pair(i, j);
}
}
}
return ERROR_PAIR;
}
void addChoices(list<array<unsigned char, N * N>> &choices, Node &node) {
while (!choices.empty()) {
node.child.push_back(newNode(choices.front()));
choices.pop_front();
}
return;
}
list<array<unsigned char, N * N>> getChoices(
const int &row, const int &col, const array<unsigned char, N * N> &grid) {
list<array<unsigned char, N * N>> choices;
for (int i = 1; i < 10; i++) {
if (canInsert(i, row, col, grid)) {
array<unsigned char, N *N> tmpGrid = grid;
tmpGrid[row + col * N] = i;
choices.push_back(move(tmpGrid));
}
}
return choices;
}
// Compute one step of computation for each node in input, and put all the
// childreen in the task vector.
void solveOneStep(vector<Node *> &nodes, vector<Node *> &tasks) {
// std::this_thread::sleep_for(std::chrono::milliseconds(2000));
// std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (solutionFound) {
for (Node *&t : nodes) {
delete t;
}
return;
}
for (Node *&n : nodes) {
if (findCell(n->grid) != ERROR_PAIR) {
pair<int, int> freeCell = findCell(n->grid);
list<array<unsigned char, N *N>> choices =
getChoices(freeCell.first, freeCell.second, n->grid);
if (choices.empty()) {
delete n;
continue;
}
addChoices(choices, *n);
for (Node *&n : n->child) { //Store all the children in tasks
tasks.push_back(n);
}
delete n;
continue;
} else if (isSolution(n->grid)) {
if (!solutionFound.load()) {
solutionFound.store(true);
printGrid(n->grid);
cout << "That's the first solution found !" << endl;
}
delete n;
return;
}
}
}
//Start the computation sequentially, until we have enough works to start all the threads togheter
vector<Node *> findChunks(Node *root, const int &nw) {
vector<Node *> tasks;
vector<Node *> nodes;
nodes.push_back(root);
while ((int)tasks.size() < nw && !solutionFound) {
tasks.clear();
solveOneStep(nodes, tasks);
if (tasks.empty()) {
vector<Node *> error;
cout << "errore" << endl;
return error;
}
nodes = tasks;
}
return tasks;
}
//Assign each part of the work to each worker
vector<vector<Node *>> splitChunks(vector<Node *> &tasks, int nw) {
int freeWorker = nw;
vector<vector<Node *>> works(nw, vector<Node *>());
for (int i = 0; i < nw; i++) {
int limit = 0;
i == nw - 1 ? limit = tasks.size()
: limit = ceil(tasks.size() / double(freeWorker));
for (int j = 0; j < limit; j++) {
works[i].push_back(tasks.back());
tasks.pop_back();
}
freeWorker--;
}
return works;
}
vector<Node *> solveTest(vector<Node *> &nodes) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
vector<Node *> results;
if (solutionFound) {
for (Node *&t : nodes) {
delete t;
}
return results;
}
for (Node *&n : nodes) {
if (findCell(n->grid) != ERROR_PAIR) { //There is an empty cell
pair<int, int> freeCell = findCell(n->grid);
list<array<unsigned char, N *N>> choices =
getChoices(freeCell.first, freeCell.second, n->grid);
if (choices.empty()) {
delete n;
continue;
}
addChoices(choices, *n); //Update the tree
for (Node *&child : n->child) {
results.push_back(child);
};
delete n;
continue;
} else if (isSolution(n->grid) && !solutionFound.load()) { //Grid is full, check for a solution
solutionFound = true;
printGrid(n->grid);
cout << "That's the first solution found !" << endl;
delete n;
return results;
} else { //Grid full but it's not a solution
delete n;
continue;
}
}
return results;
}
//Get a work from the queue
vector<Node *> getWork() {
unique_lock<mutex> lck(mtx);
auto tmp = queueWork.back();
queueWork.pop_back();
lck.unlock();
return tmp;
}
//Put a work in the queue
void pushWork(vector<Node *> &work) {
unique_lock<mutex> lck(mtx);
queueWork.push_back(work);
lck.unlock();
return;
}
struct firstThirdStage : ff_node_t<vector<Node *>> {
firstThirdStage(Node *root, const int nw) : root(root), nw(nw) {}
vector<Node *> *svc(vector<Node *> *task) {
if (task == nullptr) {
vector<Node *> tasks = findChunks(root, nw);
if (tasks.empty() && !solutionFound) { //No more moves to do, no solution.
cout << "This sudoku is unsolvable!" << endl;
delete task;
return EOS;
}
vector<vector<Node *>> works = splitChunks(tasks, nw);
for (size_t i = 0; i < works.size(); ++i) {
ff_send_out(new vector<Node *>(works[i]));
}
delete task;
return GO_ON;
}
//cout << threadSus << endl;
if (solutionFound.load()) { //After the first iteration
delete task;
return EOS;
} else {
if (!queueWork.empty()) {
vector<Node *> tmp;
tmp = getWork();
ff_send_out(new vector<Node *>(tmp));
delete task;
return GO_ON;
} else
if (++threadSus == nw) {
cout << "This sudoku is unsolvable!" << endl;
delete task;
return EOS;
}
}
delete task;
return GO_ON;
}
void svc_end() {
cout << "Done !" << endl;
}
Node *root;
const int nw;
int threadSus = 0; //Threads suspended
};
struct secondStage : ff_node_t<vector<Node *>> {
vector<Node *> *svc(vector<Node *> *task) {
vector<Node *> &t = *task;
vector<Node *> res = solveTest(t);
if (!res.empty()) {
pushWork(res);
} else {
for (auto &t : res){
delete t;
}
}
return task;
}
};
int main(int argc, char *argv[]) {
chrono::high_resolution_clock::time_point t1 =
chrono::high_resolution_clock::now();
array<unsigned char, N *N> grid = {
3, 0, 6, 5, 0, 8, 4, 0, 0, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 8, 7,
0, 0, 0, 0, 3, 1, 0, 0, 3, 0, 1, 0, 0, 8, 0, 9, 0, 0, 8, 6, 3,
0, 0, 5, 0, 5, 0, 0, 9, 0, 6, 0, 0, 1, 3, 0, 0, 0, 0, 2, 5, 0,
0, 0, 0, 0, 0, 0, 0, 7, 4, 0, 0, 5, 2, 0, 6, 3, 0, 0};
array<unsigned char, N *N> testGrid2 = {
0, 0, 0, 5, 7, 8, 4, 9, 2, 0, 0, 0, 1, 3, 4, 7, 6, 8, 0, 0, 0,
6, 2, 9, 5, 3, 1, 2, 6, 3, 0, 1, 5, 9, 8, 7, 9, 7, 4, 8, 6, 0,
1, 2, 5, 8, 5, 1, 7, 9, 2, 6, 4, 3, 1, 3, 8, 0, 4, 7, 2, 0, 6,
6, 9, 2, 3, 5, 1, 8, 7, 4, 7, 4, 5, 0, 8, 6, 3, 1, 0};
if (argc < 2) {
std::cerr << "use: " << argv[0] << " nworkers\n";
return -1;
}
array<unsigned char, N *N> testGrid = {0};
generateMatrix(12,20, testGrid);
Node *root = newNode(testGrid);
const size_t nworkers = std::stol(argv[1]);
firstThirdStage firstthird(root, nworkers);
std::vector<std::unique_ptr<ff_node>> W;
for (size_t i = 0; i < nworkers; ++i)
W.push_back(make_unique<secondStage>());
ff_Farm<vector<Node *>> farm(std::move(W), firstthird);
farm.remove_collector(); // needed because the collector is present by
// default in the ff_Farm
farm.wrap_around(); // this call creates feedbacks from Workers to the
// Emitter
// farm.set_scheduling_ondemand(); // optional
ffTime(START_TIME);
if (farm.run_and_wait_end() < 0) {
error("running farm");
return -1;
}
ffTime(STOP_TIME);
std::cout << "Time: " << ffTime(GET_TIME) << "\n";
chrono::high_resolution_clock::time_point t2 =
chrono::high_resolution_clock::now();
chrono::duration<double> time_span =
chrono::duration_cast<chrono::duration<double>>(t2 - t1);
std::cout << "It took me " << time_span.count() << " seconds." << endl;
return (0);
}
At least one cause of a leak is found using https://github.com/vmware/chap (free open source) as follows:
Gather a live core of your program just before it returns from main (for example, by using gdb to set a breakpoint there, then using the "generate" command from gdb to generate a core.
Open the core from chap and do the following from the chap prompt:
chap> count leaked
699 allocations use 0x147a8 (83,880) bytes.
That shows you that there are 699 leaked allocations.
chap> count unreferenced
692 allocations use 0x14460 (83,040) bytes.
That shows you that of the leaked allocations, all but 7 of those allocations are not referenced by any other leaked allocations.
chap> count unreferenced /extend ~>
699 allocations use 0x147a8 (83,880) bytes.
That shows you that all the leaked allocations can be reached from those unreferenced allocations, so if we understand the unreferenced allocations we understand the whole leak.
chap> summarize unreferenced
Unrecognized allocations have 692 instances taking 0x14460(83,040) bytes.
Unrecognized allocations of size 0x78 have 692 instances taking 0x14460(83,040) bytes.
692 allocations use 0x14460 (83,040) bytes.
That shows you that the unreferenced allocations are all size 0x78.
chap> redirect on
That says that the output of any subsequent commands should be redirected to files until the next "redirect off" command.
chap> show unreferenced
Wrote results to core.21080.show_unreferenced
That command shows all the unreferenced allocations and, since redirect was on, that output went to the specified file.
If we look in that output file we see that all the allocations look like this:
Used allocation at 7f0f74009870 of size 78
0: 806070304010209 108060503040705 109020508060902 509060308030407
20: 702010501070204 907040403090608 502060508020103 108010309040607
40: 206050307080409 904050201080603 7 0
60: 0 0 80
By inspection of the code, each of these objects is a Node, taking 0x58 bytes for the 9*9 std::array at offset 0 followed by 0x18 bytes for the vector header at offset 0x58, which in the node shows here has all 0 because the vector is empty and so does not need a buffer. The other thing you can see in this node is that it is for a fully filled in grid, because the first 81 bytes are all non-zero.
The above information is sufficient to determine that at least one cause of a leak is in solveOneStep, where it mis-handles the case where the grid is fully filled in but is not a solution, because in that case it simply forgets about n.
I'll leave finding any other causes of this leak to you, keeping in mind that all the leaked objects are for fully filled in grids, but not necessary solutions.
Well the problem starts with you having to use deletes at all, using std::unique_ptr would have solved the problem for you.
Seems your forgetting to delete tmp?
if (!queueWork.empty()) {
vector<Node *> tmp;
tmp = getWork(); <--- bug part 1, tmp is never deleted
ff_send_out(new vector<Node *>(tmp));
delete task; <--- bug part 2 what is deleted here???
return GO_ON;
} else
if (++threadSus == nw) {
cout << "This sudoku is unsolvable!" << endl;
delete task;
return EOS;
}
Related
I'm trying to write a function that modifies an array list by removing even numbers and duplicating odd numbers.
My code works just fine in removing the even numbers. However, it only duplicates some odd numbers.
For eg. my list contains: 12 11 13 14 15 13 10
The list L after L.duplicateORremove() should contain:
11 11 13 13 15 15 13 13
But this is what I get: 11 13 13 15 13 13
I'd like some help in figuring out why I'm getting this result.
This is my code so far:
template <class Type>
void arrayListType <Type>::duplicateORremove()
{
for(int i=0; i<length; i++)
{
if(list[i]%2==0)
{
for (int j = i; j < length - 1; j++)
list[j] = list[j + 1];
length--;
}
else
{
for (int j = length; j > i; j--)
list[j] = list[j - 1];
list[i+1] = list[i];
i++;
length++;
}
}
}
This is how my class definition and main look like:
template < class Type >
class arrayListType {
public:
arrayListType(int size = 100);
~arrayListType();
void insertEnd(const Type & insertItem);
void print() const;
void duplicateORremove();
protected:
Type * list; //array to hold the list elements
int length; //stores length of list
int maxSize; //stores maximum size of the list
};
template < class Type >
arrayListType < Type > ::arrayListType(int size) {
if (size < 0) {
cerr << "The array size must be positive. Creating " <<
"an array of size 100. " << endl;
maxSize = 100;
} else
maxSize = size;
length = 0;
list = new Type[maxSize];
assert(list != NULL);
}
template < class Type >
arrayListType < Type > ::~arrayListType() {
delete[] list;
}
template < class Type >
void arrayListType < Type > ::insertEnd(const Type & insertItem) {
if (length >= maxSize)
cerr<<"Cannot insert in a full list" << endl;
else {
list[length] = insertItem;
length++;
}
}
template < class Type >
void arrayListType < Type > ::print() const {
for (int i = 0; i < length; i++)
cout << list[i] << " ";
cout << endl;
}
int main()
{
arrayListType <int> L;
L.insertEnd(12);
L.insertEnd(11);
L.insertEnd(13);
L.insertEnd(14);
L.insertEnd(15);
L.insertEnd(13);
L.insertEnd(10);
cout << "List L before L.duplicateORremove() contains:" << endl;
L.print();
L.duplicateORremove();
cout << "List L after L.duplicateORremove() contains:" << endl;
L.print();
#include <iostream>
using namespace std;
void duplicateORremove(int list[], int length) {
for(int i=0; i<length; i++)
{
if(list[i]%2==0)
{
for (int j = i; j < length - 1; j++)
list[j] = list[j + 1];
length--;
i-=1;
}
else
{
for (int j = length; j > i; j--)
list[j] = list[j - 1];
list[i+1] = list[i];
i++;
length++;
}
}
for (int i=0; i<length; i++) {
cout << list[i];
cout << " ";
}
}
int main()
{
int arrlist[] = {12, 11, 13, 14, 15, 13, 10};
duplicateORremove(arrlist, 7);
return 0;
}
You are not resetting the 'i' value to traverse from the previous state when an even number is found. Because of that odd number taking place of an even number is skipped while looping, and, hence you will end up with a result that has some values missing in the result. And the count of missing values will be equal to the count of even number in your input.
Just add that reset condition and it will work.
Link to run the above code: Online cpp compiler
Here's a solution using Range-v3 library.
You can operate on a view of the original range.
Remove the even elements.
Duplicate each element of the remaining list (the odd ones).
Then convert the view back into a vector and return it.
[Demo]
#include <fmt/ranges.h>
#include <range/v3/all.hpp>
template <typename Range>
auto duplicate_or_remove(Range&& r) {
using namespace ranges::v3;
auto even = [](int i) { return 0 == i % 2; };
return r
| views::remove_if(even)
| views::for_each([](auto e){ return yield_from(views::repeat_n(e, 2)); })
| to_vector;
}
int main() {
std::vector<int> v{12, 11, 13, 14, 15, 13, 10};
fmt::print("{}", duplicate_or_remove(v));
}
// Outputs:
//
// [11, 11, 13, 13, 15, 15, 13, 13]
Going back to your code, notice that you cannot simply work over your input list. What would happen if the list only contained odd numbers? For the first element, you would be writing beyond the memory reserved for the list. Instead, if you need to stick to using arrays, what you can do is:
Count the odd elements in your input list.
Create a new array sized twice the number of odd elements in the input list.
Walk over the input list and, for each odd element, add it twice to the newly created array.
Return a pair consisting of the new array and its size.
The code below also uses a nice trick to avoid passing the length of an array to a funcion if what you are passing is an array and not a pointer.
[Demo]
#include <iostream> // cout
#include <utility> // pair
auto is_odd = [](int i){ return (i % 2) == 1; };
template <size_t length>
size_t count_odd_elements(int (&list)[length]) {
size_t ret{};
for (size_t i{0}; i < length; ++i) {
if (is_odd(list[i])) {
ret++;
}
}
return ret;
}
template <size_t length>
auto duplicate_or_remove(int (&list)[length]) {
size_t odd_elements{ count_odd_elements(list) };
size_t ret_size{odd_elements * 2};
int* ret = new int[ret_size];
size_t head{};
for (size_t i{0}; i < length; ++i) {
int n{ list[i] };
if (is_odd(n)) {
ret[head++] = n;
ret[head++] = n;
}
}
return std::pair<int*, size_t>{ret, ret_size};
}
void print_list(int list[], size_t length) {
std::cout << "[";
for (size_t i{0}; i < length; ++i) {
std::cout << ((i == 0) ? "" : ", ") << list[i];
}
std::cout << "]";
}
int main() {
int arrlist[] = {12, 11, 13, 14, 15, 13, 10};
auto [result, result_size] = duplicate_or_remove(arrlist);
print_list(result, result_size);
delete[] result;
}
// Outputs:
//
// [11, 11, 13, 13, 15, 15, 13, 13]
Again, using std::vector instead of arrays simplify things a lot:
[Demo]
#include <fmt/ranges.h>
#include <iostream> // cout
#include <vector>
auto is_odd = [](int i){ return (i % 2) == 1; };
auto duplicate_or_remove(const std::vector<int>& list) {
std::vector<int> ret{};
for (auto i : list) {
if (is_odd(i)) {
ret.push_back(i);
ret.push_back(i);
}
}
return ret;
}
int main() {
std::vector<int> v{12, 11, 13, 14, 15, 13, 10};
auto result{ duplicate_or_remove(v) };
fmt::print("{}", result);
}
Brief recap: I have a C++ multithreading sudoku solver, for which I want to improve the efficiency, i need your help.
I'm implementing a brute force sudoku solver in multithreading in C++. The main struct is a tree and the all logic is this: I start reading the initial matrix in input and this will be my root node, then I find the first empty cell, I find all the possible numbers that could fit that position, and for each possibility I create a sub-node of the parent node, so that each node will have a child-node for each possible number. The tree continues to grow in this way until a solution is met, that is a node has no more free cells(so it is full), and the node grid satisfy all the rules of the sudoku.
I tried to implement this algorithm in multithreading like this: I follow the exactly same logic of above sequentially but making one step each time, storing all the children I have met until that moment (each child will be a path, and so a tree) in a vector. If the children are less than the threads chosen by the user, then I solve them sequentially and I make one more step(children will grow). When I have more children than threads, then I split the children for each thread, and I start the threads each one with his part(that is a tree).
Now, taking into account that the "brute force" approch and that "only std lib" requirements are mandatory, so I can't do in a different way, but I can change of course the logic on how to implement this.
The question is: how can I improve the efficiency of this program ? All the suggestions that uses only std lib are welcome.
#define UNASSIGNED 0
#define N 9
#define ERROR_PAIR std::make_pair(-1, -1)
using namespace std;
atomic<bool> solutionFound{false};
//Each node has a sudokuMatrix and some sub-trees
struct Node {
vector<vector<int>> grid;
vector<Node *> child;
};
Node *newNode(const vector<vector<int>> &newGrid) {
Node *temp = new Node;
temp->grid = newGrid;
return temp;
}
//Check if a number can be inserted in a given position
bool canInsert(const int &val, const int &row_, const int &col_,
const vector<vector<int>> &grid) {
// Check column
for (int row = 0; row < N; row++) {
if (grid[row][col_] == val) return false;
}
// Check row
for (int col = 0; col < N; col++) {
if (grid[row_][col] == val) return false;
}
// check box
for (int row = 0; row < N; row++) {
for (int col = 0; col < N; col++) {
if (row / 3 == row_ / 3 &&
col / 3 == col_ / 3) { // they are in the same square 3x3
if ((grid[row][col] == val)) return false;
}
}
}
return true;
}
//Check if the sudoku is solved
bool isSafe(const vector<vector<int>> &grid)
{
// Hashmap for row column and boxes
unordered_map<int, int> row_[9], column_[9], box[3][3];
for (int row = 0; row < N; row++) {
for (int col = 0; col < N; col++) {
// mark the element in row column and box
row_[row][grid[row][col]] += 1;
column_[col][grid[row][col]] += 1;
box[row / 3][col / 3][grid[row][col]] += 1;
// if an element is already
// present in the hashmap
if (box[row / 3][col / 3][grid[row][col]] > 1 ||
column_[col][grid[row][col]] > 1 ||
row_[row][grid[row][col]] > 1)
return false;
}
}
return true;
}
//Find the first empty cell
pair<int, int> findCell(const vector<vector<int>> &grid) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (grid[i][j] == UNASSIGNED) {
return make_pair(i, j);
}
}
}
return ERROR_PAIR;
}
//Find all the numbers i can insert in a given position, and update the matrix with that number. Return
//the set of all the matrixes(one for each possibility).
list<vector<vector<int>>> getChoices(const int &row, const int &col,
const vector<vector<int>> &grid) {
list<vector<vector<int>>> choices;
for (int i = 1; i < 10; i++) {
if (canInsert(i, row, col, grid)) {
// cout << "posso inserire =" << i << endl;
vector<vector<int>> tmpGrid = grid;
tmpGrid[row][col] = i;
choices.push_back(tmpGrid);
}
}
return choices;
}
//Update the childreen of a node.
void addChoices(list<vector<vector<int>>> &choices, Node &node) {
while (!choices.empty()) {
node.child.push_back(newNode(choices.front()));
choices.pop_front();
}
return;
}
//Compute one step of computation for each node in input, and put all the childreen in the task vector.
void solveOneStep(vector<Node *> &nodes, const int &nw, vector<Node *> &tasks) {
if (solutionFound) return;
for (Node *&n : nodes) {
if (findCell(n->grid) != ERROR_PAIR) {
pair<int, int> freeCell = findCell(n->grid);
list<vector<vector<int>>> choices =
getChoices(freeCell.first, freeCell.second, n->grid);
if (choices.empty()) {
continue;
}
addChoices(choices, *n);
for (Node *&n : n->child) {
tasks.push_back(n);
}
continue;
} else if (isSafe(n->grid)) {
if (!solutionFound.load()) {
solutionFound.store(true);
printGrid(n->grid);
cout << "That's the first solution found !" << endl;
}
return;
}
}
}
//Compute step by step the computation until you reach a level of the entire tree of nodes where
//the nodes of that level are more than the number of worker(NW) choose by the user.
vector<Node *> splitChunks(Node *root, const int &nw) {
vector<Node *> tasks;
vector<Node *> nodes;
nodes.push_back(root);
while ((int)tasks.size() < nw && !solutionFound) {
tasks.clear();
solveOneStep(nodes, nw, tasks);
nodes = tasks;
}
return tasks;
}
//Solve recursively all the sub-trees of all the nodes given in input, until a solution is found or no
//solution exist.
void solveSubTree(vector<Node *> &nodes, const int &nw,) {
if (solutionFound) return;
for (Node *&n : nodes) {
if (findCell(n->grid) != ERROR_PAIR) {
pair<int, int> freeCell = findCell(n->grid);
list<vector<vector<int>>> choices =
getChoices(freeCell.first, freeCell.second, n->grid);
if (choices.empty()) {
continue;
}
addChoices(choices, *n);
solveSubTree(n->child, nw);
} else if (isSafe(n->grid)) {
if (!solutionFound.load()) {
solutionFound.store(true);
printGrid(n->grid);
std::cout << "That's the first solution found !" << endl;
}
return;
}
}
}
int main(int argc, char *argv[]) {
if (argc != 2) {
cout << "Usage is: nw " << endl;
return (-1);
}
//A test matrix.
vector<vector<int>> grid =
{ { 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 8, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 } };
Node *root = newNode(grid);
vector<thread> tids;
const int nw = atoi(argv[1]); //Number of worker
vector<vector<Node *>> works(nw, vector<Node *>());
vector<Node *> tasks = splitChunks(root, nw);
//Split the tasks for each thread, the main thread takes the last part of the work.
for (int i = 0; i < nw; i++) {
int limit = 0;
i == nw - 1 ? limit = tasks.size() : limit = tasks.size() / nw;
for (int j = 0; j < limit; j++) {
works[i].push_back(tasks.back());
tasks.pop_back();
}
}
//Start each thread, and then the main thread start his computation.
for (int i = 0; i < nw - 1; i++) {
tids.push_back(thread(solveSubTree, ref(works[i]), ref(nw)));
}
solveSubTree(works[nw - 1], nw, t1); // Main thread do last part of the work
for (thread &t : tids) {
t.join();
}
std::cout << "end" << endl;
return (0);
}
Here are several points to improve the efficiency of the reference implementation:
using vector<vector<int>> for 2D array is far from being efficient: it is not contiguous in memory and cause many slow allocations. A big flatten array should be preferred.
unordered_map<int, int> for set-like operations are not needed since the integers in the sets are in a small (contiguous) range. Using a simple array is much faster.
some copies are not needed and can be removed with std::move.
as integers in the grid are small, char can be used over int (to reduce the memory footprint, to keep data in CPU caches and to possibly make allocations faster).
I see one new but no delete in the code...
The work between threads seems clearly unbalanced in many case resulting in a slower parallel execution, a load balancing should be performed to scale better. One way is to do that is to use task scheduling.
One can use heuristics to drastically speed up the exploration. To begin with, I advise you to look constraint satisfaction problem (CSP) because CSP solvers known to be very good at solving it. More general and theoretical information can be found in the book Artificial Intelligence: a modern approach.
Here is a code applying the first remarks resulting in a 5 times faster execution on my machine (note that the grid has been modified in the main) :
#define UNASSIGNED 0
#define N 9
#define ERROR_PAIR std::make_pair(-1, -1)
using namespace std;
void printGrid(const array<char, N*N>& grid)
{
for (int row = 0; row < N; row++)
{
for (int col = 0; col < N; col++)
{
cout << (int)grid[row*N+col] << " ";
}
cout << endl;
}
}
atomic<bool> solutionFound{false};
//Each node has a sudokuMatrix and some sub-trees
struct Node {
array<char, N*N> grid;
vector<Node *> child;
};
Node *newNode(const array<char, N*N> &newGrid) {
Node *temp = new Node;
temp->grid = newGrid;
return temp;
}
//Check if a number can be inserted in a given position
bool canInsert(const int &val, const int &row_, const int &col_,
const array<char, N*N> &grid) {
// Check column
for (int row = 0; row < N; row++) {
if (grid[row*N+col_] == val) return false;
}
// Check row
for (int col = 0; col < N; col++) {
if (grid[row_*N+col] == val) return false;
}
// check box
for (int row = 0; row < N; row++) {
for (int col = 0; col < N; col++) {
if (row / 3 == row_ / 3 &&
col / 3 == col_ / 3) { // they are in the same square 3x3
if ((grid[row*N+col] == val)) return false;
}
}
}
return true;
}
//Check if the sudoku is solved
bool isSafe(const array<char, N*N> &grid)
{
// No need for a hashmap for row column and boxes,
// just an array since associated values are small integer
char row_[9][N+1] = {0};
char column_[9][N+1] = {0};
char box[3][3][N+1] = {0};
for (int row = 0; row < N; row++) {
for (int col = 0; col < N; col++) {
// mark the element in row column and box
row_[row][grid[row*N+col]] += 1;
column_[col][grid[row*N+col]] += 1;
box[row / 3][col / 3][grid[row*N+col]] += 1;
// if an element is already
// present in the hashmap
if (box[row / 3][col / 3][grid[row*N+col]] > 1 ||
column_[col][grid[row*N+col]] > 1 ||
row_[row][grid[row*N+col]] > 1)
return false;
}
}
return true;
}
//Find the first empty cell
pair<int, int> findCell(const array<char, N*N> &grid) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
if (grid[i*N+j] == UNASSIGNED) {
return make_pair(i, j);
}
}
}
return ERROR_PAIR;
}
//Find all the numbers i can insert in a given position, and update the matrix with that number. Return
//the set of all the matrixes(one for each possibility).
list<array<char, N*N>> getChoices(const int &row, const int &col,
const array<char, N*N> &grid) {
list<array<char, N*N>> choices;
for (int i = 1; i < 10; i++) {
if (canInsert(i, row, col, grid)) {
// cout << "posso inserire =" << i << endl;
array<char, N*N> tmpGrid = grid;
tmpGrid[row*N+col] = i;
choices.push_back(std::move(tmpGrid));
}
}
return choices;
}
//Update the childreen of a node.
void addChoices(list<array<char, N*N>> &choices, Node &node) {
while (!choices.empty()) {
node.child.push_back(newNode(choices.front()));
choices.pop_front();
}
return;
}
//Compute one step of computation for each node in input, and put all the childreen in the task vector.
void solveOneStep(vector<Node *> &nodes, const int &nw, vector<Node *> &tasks) {
if (solutionFound) return;
for (Node *&n : nodes) {
if (findCell(n->grid) != ERROR_PAIR) {
pair<int, int> freeCell = findCell(n->grid);
list<array<char, N*N>> choices =
getChoices(freeCell.first, freeCell.second, n->grid);
if (choices.empty()) {
continue;
}
addChoices(choices, *n);
for (Node *&n : n->child) {
tasks.push_back(n);
}
continue;
} else if (isSafe(n->grid)) {
if (!solutionFound.load()) {
solutionFound.store(true);
printGrid(n->grid);
cout << "That's the first solution found !" << endl;
}
return;
}
}
}
//Compute step by step the computation until you reach a level of the entire tree of nodes where
//the nodes of that level are more than the number of worker(NW) choose by the user.
vector<Node *> splitChunks(Node *root, const int &nw) {
vector<Node *> tasks;
vector<Node *> nodes;
nodes.push_back(root);
while ((int)tasks.size() < nw && !solutionFound) {
tasks.clear();
solveOneStep(nodes, nw, tasks);
nodes = tasks;
}
return tasks;
}
//Solve recursively all the sub-trees of all the nodes given in input, until a solution is found or no
//solution exist.
void solveSubTree(vector<Node *> &nodes, const int &nw) {
if (solutionFound) return;
for (Node *&n : nodes) {
if (findCell(n->grid) != ERROR_PAIR) {
pair<int, int> freeCell = findCell(n->grid);
list<array<char, N*N>> choices =
getChoices(freeCell.first, freeCell.second, n->grid);
if (choices.empty()) {
continue;
}
addChoices(choices, *n);
solveSubTree(n->child, nw);
} else if (isSafe(n->grid)) {
if (!solutionFound.load()) {
solutionFound.store(true);
printGrid(n->grid);
std::cout << "That's the first solution found !" << endl;
}
return;
}
}
}
int main(int argc, char *argv[]) {
if (argc != 2) {
cout << "Usage is: nw " << endl;
return (-1);
}
//A test matrix.
array<char, N*N> grid =
{ 0, 0, 0, 0, 0, 0, 2, 0, 0,
0, 8, 0, 0, 0, 7, 0, 9, 0,
6, 0, 2, 0, 0, 0, 5, 0, 0,
0, 7, 0, 0, 6, 0, 0, 0, 0,
0, 0, 0, 9, 0, 1, 0, 0, 0,
0, 0, 0, 0, 2, 0, 0, 4, 0,
0, 0, 5, 0, 0, 0, 6, 0, 3,
0, 9, 0, 4, 0, 0, 0, 7, 0,
0, 0, 6, 0, 0, 0, 0, 0, 0 };
Node *root = newNode(grid);
vector<thread> tids;
const int nw = atoi(argv[1]); //Number of worker
vector<vector<Node *>> works(nw, vector<Node *>());
vector<Node *> tasks = splitChunks(root, nw);
//Split the tasks for each thread, the main thread takes the last part of the work.
for (int i = 0; i < nw; i++) {
int limit = 0;
i == nw - 1 ? limit = tasks.size() : limit = tasks.size() / nw;
for (int j = 0; j < limit; j++) {
works[i].push_back(tasks.back());
tasks.pop_back();
}
}
//Start each thread, and then the main thread start his computation.
for (int i = 0; i < nw - 1; i++) {
tids.push_back(thread(solveSubTree, ref(works[i]), ref(nw)));
}
solveSubTree(works[nw - 1], nw); // Main thread do last part of the work
for (thread &t : tids) {
t.join();
}
std::cout << "end" << endl;
return (0);
}
After reading the first paragraph: Your approach is very inefficient; multithreading won't safe it.
Consider this: There are 4 x 81 questions you could ask: Where in column c does the number n go? Where in row r does the number n go? Where in 3x3 box b does the number n go? Which number goes into the cell at column c, row r?
If k numbers have been written down, 4k of these questions are already answered. For the rest, find the number of possible valid answers according to the Sudoku rules. If a question has no valid answers, there is no solution and you backtrack. If a question has one valid answer, you pick that answer. Otherwise you try the answers for a question with 2 possible answers in turn, or for a question with 3 possible answers if there are none with 1 or 2 answers, etc.
For most newspaper problems there will be very little backtracking.
I am doing the program in which i am checking that if the array is balance or not like the array
int a5[] = {2, 1, 4, 3}; // balance array because i got even number on even position so program return 1
int a5[] = {3, 1, 4, 3}; // un balance array because i got odd number on even position so program return 0
This is my program which i am trying
int araay(int arg[], int length);
int main()
{
int a6[] = {3, 3, 4, 4};
int a7[] = {2, 2, 3, 4};
int a8[] = {4, 1, 2, 3};
int a9[] = {1, 1};
araay (a7,sizeof(a7));
}
int araay (int arg[], int length)
{
int sumEven = 0;
int sumOdd = 0;
for (int i=0; i<=length; i=i+2)
{
if (arg[i]%2 == 0)
{
sumEven++;
}
else
sumOdd++;
}
for (int i=1; i<=length; i=i+2)
{
if (arg[i]%2 == 0)
{
sumEven++;
}
else
sumOdd++;
}
return 0;
}
in return it always return me 00000 something like zero everytime
Following may help: (http://ideone.com/NttqbY)
bool is_balanced(const std::vector<std::size_t>& v)
{
for (std::size_t i = 0; i != v.size(); ++i) {
if ((i % 2) != (v[i] % 2)) {
return false;
}
}
return true;
}
Thanks all for your comments and help
This is what i tried
int araay(int arg[], int length);
int main()
{
int a6[] = {3, 3, 4, 4};
int a7[] = {2, 3, 2, 3};
int a8[] = {4, 1, 2, 3};
int a9[] = {1, 1};
araay (a7,3);
}
int araay (int arg[], int length)
{
int sumEven = 0;
int sumOdd = 0;
for (int i=0; i<=length; i+=2)
{
if (arg[i]%2 != 0)
{
cout<<"unbalanced"<<endl;
// return 0;
}
else
{
sumEven++;
}
}
for (int i=1; i<=length; i=i+2)
{
if (arg[i]%2 == 0)
{
cout<<"unbalanced"<<endl;
sumEven++;
}
else
{
sumOdd++;
// return 0;
}
}
return 0;
}
but the answer of #jarod is looking more suitable and easy
This is what you can do
#include <iostream>
int check(int arg[])
{
for (auto i = 0; i < sizeof(arg); ++i)
{
if ((i % 2) != (arg[i] % 2))
{
return 0;
}
}
return 1;
}
void main()
{
int a[] = { 1, 2, 3, 4 };
int b[] = { 2, 3, 4, 5 };
int c[] = { 2, 2, 3, 3 };
std::cout << "a = " << check(a) << std::endl;
std::cout << "b = " << check(b) << std::endl;
std::cout << "c = " << check(c) << std::endl;
getchar();
}
How do I sort an array without using a loop in C++? I think it might use recursion, but I do not know how to implement it.
Use std::sort defined in algorithm header file
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int a[]={5,3,4,1,2};
sort(a,a+5);
for(int i=0;i<5;i++)
cout<<a[i]<<" "; // 1 2 3 4 5
return 0;
}
//C++
void bubblesort(vector<int> &arr, int iteration) {
if(iteration == 0)
return;
bubbleswap(arr, 0, 1, iteration);
bubblesort(arr, iteration-1);
}
void bubbleswap(vector<int> &arr, int i, int j, int n) {
if(j>=n)
return ;
if(arr[i] < arr[j]){
swap(arr[i], arr[j]);
}
bubbleswap(arr, i+1, j+1, n);
}
void sort(vector<int> &arr) {
int n = arr.size();
if(n<=1)
return ;
bubblesort(arr, n);
}
Recursive Selection Sort
#include <iostream>
#include <vector>
using namespace std;
//----------------------------------------------------------
int recursive_min(vector<int>& a, size_t first) {
//base case
if (first + 1 >= a.size()) {
return first;
}
else {
size_t min_index {first};
int temp_index {recursive_min(a, first + 1)};
if (a[min_index] > a[temp_index]) {
min_index = temp_index;
}
return min_index;
}
}
//----------------------------------------------------------
void selectionSort(vector<int>& a, size_t step = 0) {
//base case
if (step + 1 >= a.size()) {
return;
}
else {
int temp_index {recursive_min(a, step + 1)};
if (a[step] > a[temp_index]) {
swap(a[step], a[temp_index]);
}
selectionSort(a, step + 1);
}
}
//---------------------------------------------------------
int main() {
vector<int> vec {11, 23, 2, 50, 3, 8, 1, 4, 5};
selectionSort(vec);
for (int i : vec) {
cout << i << " ";
}
}
Recursive Insertion Sort
#include <iostream>
#include <vector>
using namespace std;
int recursive_insert(vector<int>& a, int key, int i) {
//base case
if (i <= -1 || a[i] <= key) {
return i;
}
else {
a[i + 1] = a[i];
return recursive_insert(a, key, i - 1);
}
}
//-----------------------------------------------------------------------------
void insertion_sort(vector<int>& a, size_t j = 1) {
//base case
if (j >= a.size()) {
return;
}
else {
int key = a[j];
int i = recursive_insert(a, a[j], j - 1);
a[i + 1] = key;
insertion_sort(a, j + 1);
}
}
//-----------------------------------------------------------------------------
int main() {
vector<int> vec {11, 23, 2, 50, 3, 8, 1, 4, 5};
insertion_sort(vec);
for (int i : vec) {
cout << i << " ";
}
}
#include<stdio.h>
int * sort(int *p,int i,int j,int size)
{
if(i<size)
{
if(j<size-i-1)
{
if(p[j]>p[j+1])
{
int temp = p[j];
p[j] = p[j+1];
p[j+1] = temp;
}
}
else
{
j=-1;
++i;
}
p = sort(p,i,++j,size);
}
return p;
}
Below is how to use it
int main()
{
int array[] ={1,5,2,7,3};
int len = sizeof(array)/sizeof(int);
int *a = sort(array,0,0,len);
for(int i=0;i<len;i++)
{
printf("\n array[%d]->%d",i,a[i]);
}
}
I think you are looking for the Quicksort Algorithm
There are more ways to sort an array.
If you are trying to implement a loop recursively, you can check out a wikipedia article. It is well explained under "Recursion computer science".
Otherwise you can try to implement different sorting algorithms. The well known are Quicksort and Mergesort.
There are many sorting algorithms
Well, I'm writing a Python interpreter and didn't write loop yet. I got the codebase from some website and rewrite the loop by some recursion. It works. :D
def quickSort(arr, low, high):
def jLoop(low, high, pivot, i, j):
if j >= high:
temp = arr[high]
arr[high] = arr[i+1]
arr[i+1] = temp
return (i+1)
else:
if arr[j] <= pivot:
i = i+1
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
return jLoop(low, high, pivot, i, j+1)
def partition(low, high):
i = (low - 1)
pivot = arr[high]
return jLoop(low, high, pivot, i, low)
def quick(low, high):
if low < high:
pi = partition(low, high)
quick(low, pi-1)
quick(pi+1, high)
quick(low, high)
return arr
my_list = [0, 6, 3, 1, 2, 4, 7, 5]
length = 8
print quickSort(my_list, 0, 7)
my_list = [9, 0, 8, 1, 7, 2, 6, 3, 5, 4]
length = 10
print quickSort(my_list, 0, 9)
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;
}
}