C++ vector reference works funny - c++

I have written a simple c++ algorithm to calculate permutations of a vector. The below code works fine if I change this 13. line
vector<int>& pp = p.front();
to this
vector<int> pp = p.front();
I cannot understand why. I don`t think it is caused by reallocation. Could someone explain?
#include <vector>
using namespace std;
class Solution {
public:
void f(vector<vector<int> >& p, vector<int>& num)
{
if (p.front().size() == num.size()) return;
int k = p.size();
while (k)
{
vector<int>& pp = p.front();
for (int toAdd : num)
{
bool found = false;
for (int i = 0; i < pp.size(); i++)
{
if (pp[i] == toAdd)
{
found = true;
break;
}
}
if (!found)
{
vector<int> newp;
for (int i = 0; i < pp.size(); i++)
{
newp.push_back(pp[i]);
}
newp.push_back(toAdd);
p.push_back(newp);
}
}
p.erase(p.begin());
k--;
}
f(p, num);
}
vector<vector<int> > permute(vector<int> &num)
{
vector<vector<int>> r;
r.reserve(2 << num.size());
for (int i = 0; i < num.size(); i++)
{
r.push_back(vector<int>());
r[i].push_back(num[i]);
}
f(r, num);
return r;
}
};
int main()
{
Solution s;
vector<int> num{ 6, 3, 2, 7, 4, -1 };
auto a = s.permute(num);
a.clear();
return 0;
}

It's because of this statement:
p.push_back(newp)
That invalidates all references to entries in the vector p, because it can reallocate the contents.

Related

Why is my code to detect a cycle in a graph not printing anything?

I have written the code to check if a cycle exists or not in a graph using breadth-first traversal.
If I declare the adjacency list as vectoradj[n]; then it's okay.
But the problem arises when I use vector<vector>adj(n)
Can someone tell me what is the error? and how can I use the latter option to run my code?
#include <bits/stdc++.h>
using namespace std;
bool checkForCycle(int s, int V, vector<vector<int>>adj, vector<int> &visited)
{
queue<pair<int, int>> q;
visited[s] = true;
q.push({s, -1});
while (!q.empty())
{
int node = q.front().first;
int par = q.front().second;
q.pop();
for (auto it : adj[node])
{
if (!visited[it])
{
visited[it] = true;
q.push({it, node});
}
else if (par != it)
return true;
}
}
return false;
}
bool isCycle(int V,vector<vector<int>>adj)
{
vector<int> vis(V - 1, 0);
for (int i = 1; i <= V; i++)
{
if (!vis[i])
{
if (checkForCycle(i, V, adj, vis))
return true;
}
}
}
int main() {
int n, m;
cout<<"Enter number of vertices :\n";
cin>>n;
cout<<"Enter number of edges :\n";
cin>>m;
vector<vector<int>>adj(n);
for(int i=0; i<m; i++) {
int u, v;
cin>>u>>v;
adj[u].push_back(v);
adj[v].push_back(u);
}
cout<<endl;
if(isCycle(n,adj))
cout<<"cycle present int the graph";
else
cout<<"No cycle present";
return 0;
}
okay so the error resolves if I use
vector<vector<int>>adj(n+1);
instead of
vector<vector<int>>adj(n);

Process returned -1073741571 (0xC00000FD) on my c++ code [duplicate]

This question already has an answer here:
Clion exit code -1073741571 (0xC00000FD)
(1 answer)
Closed 2 years ago.
The c++ code below works fine for some inputs, but it is stuck at test 9 (number of inputs here is 6000) where it gives me this message "Process returned -1073741571 (0xC00000FD)".
This code reads information for n babies (their gender and name). Next it counts the appearances of each name then sorts the list of structures according to the appearances. Finally, it removes the duplicates and prints the top m female names and top m male names.
What does this error mean and what do I need to change to eliminate this error?
#include <iostream>
#include <fstream>
#include <algorithm>
#include <string.h>
using namespace std;
ifstream fin("input.txt");
struct baby
{
string gender,name;
int cnt;
};
bool cmp(baby a,baby b)
{
if (a.cnt>b.cnt)
return true;
else if (a.cnt==b.cnt && a.name<b.name)
return true;
return false;
}
int howmany(baby babies[],int n,int i)
{
int cnt=0;
for (int j=0; j<n; j++)
{
if (babies[i].name==babies[j].name && babies[i].gender==babies[j].gender)
{
cnt++;
}
}
return cnt;
}
void getData(baby babies[],int n)
{
for (int i=0; i<n; i++)
{
fin>>babies[i].gender>>babies[i].name;
}
}
int removeDuplicates(baby babies[],int n)
{
int j=0;
for (int i=0; i<n-1; i++)
{
if (babies[i].name!=babies[i+1].name)
babies[j++]=babies[i];
}
babies[j++]=babies[n-1];
return j;
}
int main()
{
int n,i,top,j;
fin>>n>>top;
baby babies[50000];
getData(babies,n);
for (i=0; i<n; i++)
{
babies[i].cnt=howmany(babies,n,i);
}
sort(babies,babies+n,cmp);
j=removeDuplicates(babies,n);
int cnt=0;
for (int i=0; i<j; i++)
{
if (cnt<top)
{
if (babies[i].gender=="F")
{
cout<<babies[i].name<<" ";
cnt++;
}
}
}
cout<<endl;
cnt=0;
for (int i=0; i<j; i++)
{
if (cnt<top)
{
if (babies[i].gender=="M")
{
cout<<babies[i].name<<" ";
cnt++;
}
}
}
return 0;
}
As you can see in Window's NT status reference, error code 0xC00000FD means stack overflow (usually caused by infinite recursion). In your case, it seems that you simply allocate a far too large array on the stack (line 57, baby babies[50000];), which is an array of size 50000*20=1000000. The simplest solution will be a dynamic allocation
baby* babies = new baby[50000];
// Your code here
delete[] babies;
A better solution would be to use std::vector which is a dynamic array that can grow and shrink. The simplest thing to do is to take a vector of size 50000, this way:
#include <vector>
...
std::vector<baby> babies(50000);
However, this is a poor solution as your pre-allocate 50000 elements even though you probably need much much less, and a better solution would be to add an element on-demand, using .push_back(element) method, or in your case, allocate n elements to the vector (impossible in a stack-allocated array).
I added your code with some modifications of mine:
#include <vector>
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
ifstream fin("input.txt");
struct baby
{
string gender;
string name;
int cnt = 0;
};
bool cmp(const baby& a, const baby& b)
{
if (a.cnt > b.cnt) {
return true;
}
return a.cnt == b.cnt && a.name < b.name;
}
bool are_equal(const baby& lhs, const baby& rhs)
{
return lhs.gender == rhs.gender && lhs.name == rhs.name;
}
int howmany(const std::vector<baby>& babies, int i)
{
int cnt = 0;
for (int j = 0; j < babies.size(); j++)
{
if (babies[i].name == babies[j].name && babies[i].gender == babies[j].gender)
{
cnt++;
}
}
return cnt;
}
void getData(std::vector<baby>& babies)
{
for (int i = 0; i < babies.size(); i++)
{
fin >> babies[i].gender >> babies[i].name;
}
}
int removeDuplicates(std::vector<baby>& babies)
{
int j = 0;
for (int i = 0; i < babies.size() - 1; i++)
{
if (babies[i].name != babies[i + 1].name) {
babies[j++] = babies[i];
}
}
babies[j++] = babies.back();
return j;
}
void remove_duplicates_improved(std::vector<baby>& babies)
{
babies.erase(babies.begin(), std::unique(babies.begin(), babies.end(), are_equal));
}
int main()
{
int n;
int top;
fin >> n >> top;
std::vector<baby> babies(n);
getData(babies);
for (int i = 0; i < n; i++)
{
babies[i].cnt = howmany(babies, i);
}
sort(babies.begin(), babies.begin() + n, cmp);
remove_duplicates_improved(babies);
int cnt = 0;
for (int i = 0; i < babies.size(); i++)
{
if (cnt < top)
{
if (babies[i].gender == "F")
{
cout << babies[i].name << " ";
cnt++;
}
}
}
cout << endl;
cnt = 0;
for (int i = 0; i < babies.size(); i++)
{
if (cnt < top)
{
if (babies[i].gender == "M")
{
cout << babies[i].name << " ";
cnt++;
}
}
}
return 0;
}
Good luck

C++: Fast algorithm for finding minimum sum of cycle edges

I have an undirected weighted graph and want to find the minimum sum of all cycles edges.
That means if I have no cycle, the answer is 0.
If I have one cycle the answer is the minimum edge weight of that cycle.
And if I have more than one cycle it's the sum of those minimum weights.
My algorithm I implemented, uses some kind of Prims algorithm.
I just add the heaviest edges and when a cycle would be formed the weight is summed to the answer value instead.
I thought it is correct as all my test cases show the right answer.
But somewhere has to be an error, I just couldn't find it yet.
struct connection {
int a, b, cost;
bool operator<(const connection rhs) const {
return cost < rhs.cost || (cost == rhs.cost && (a < rhs.a || (a == rhs.a && b < rhs.b)));
}
};
int n, m, researchers; // Amount of vertices, edges
std::list<connection> *adj; // Array of adjancency lists
std::list<int> *used;
std::set<connection> priorityQ;
void addEdge(int v, int w, int cost) {
connection temp;
temp.a = v;
temp.b = w;
temp.cost = cost;
adj[v].push_back(temp);
temp.a = w;
temp.b = v;
adj[w].push_back(temp);
}
bool isUsed(int u, int v) {
for (std::list<int>::iterator it = used[u].begin(); it != used[u].end(); ++it) {
int te = *it;
if (te == v) return true;
}
return false;
}
void expand(int u) {
for (std::list<connection>::iterator it = adj[u].begin(); it != adj[u].end(); ++it) {
connection v = *it;
if (isUsed(u, v.b)) continue;
used[v.b].push_back(u);
used[u].push_back(v.b);
priorityQ.insert(v);
}
}
void PrimR(int u, bool added[]) {
added[u] = true;
expand(u);
}
// Prim algorithm
void Prim(int u, bool added[]) {
added[u] = true;
expand(u);
while (priorityQ.size() > 0) {
connection now = *priorityQ.rbegin();
priorityQ.erase(*priorityQ.rbegin());
if (added[now.b]) {
researchers += now.cost;
}
else {
PrimR(now.b, added);
}
}
}
int main()
{
int t;
// loop over all test cases
scanf("%d ", &t);
for (int i = 1; i <= t; i++) {
// read input nodes n, connections m
scanf("%d %d", &n, &m);
adj = new std::list<connection>[n];
//read connections and save them
for (int j = 0; j < m; j++) {
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
addEdge(a - 1, b - 1, c);
}
researchers = 0;
// Use of prim with heaviest edges first
bool *added = new bool[n];
used = new std::list<int>[n];
for (int j = 0; j < n; j++) {
added[j] = false;
}
for (int j = 0; j < n; j++) {
if (!added[j]) {
Prim(j, added);
}
}
// print desired output
printf("Case #%d: %d\n", i, researchers);
delete[] adj;
delete[] added;
delete[] used;
}
return 0;
}
Do you know what I'm doing wrong?
I didn't consider, that between two nodes there could be multiple connections.
My following code solves this:
struct connection {
int a, b, cost, id;
bool operator<(const connection rhs) const {
return cost < rhs.cost || (cost == rhs.cost && id < rhs.id);
}
};
int n, m, researchers; // Amount of vertices, edges
std::list<connection> *adj; // Array of adjancency lists
std::set<connection> priorityQ;
void addEdge(int v, int w, int cost, int id) {
connection temp;
temp.a = v;
temp.b = w;
temp.cost = cost;
temp.id = id;
adj[v].push_back(temp);
temp.a = w;
temp.b = v;
adj[w].push_back(temp);
}
void deleteEdge(int v, int w, int id) {
for (std::list<connection>::iterator it = adj[v].begin(); it != adj[v].end(); ++it) {
if ((*it).id == id) {
adj[v].erase(it);
break;
}
}
for (std::list<connection>::iterator it = adj[w].begin(); it != adj[w].end(); ++it) {
if ((*it).id == id) {
adj[w].erase(it);
break;
}
}
}
void expand(int u) {
for (std::list<connection>::iterator it = adj[u].begin(); it != adj[u].end(); ++it) {
connection v;
v.a = (*it).a < (*it).b ? (*it).a : (*it).b;
v.b = (*it).a < (*it).b ? (*it).b : (*it).a;
v.cost = (*it).cost;
v.id = (*it).id;
priorityQ.insert(v);
}
}
void PrimR(int u, bool added[]) {
added[u] = true;
expand(u);
}
// Prim algorithm
void Prim(int u, bool added[]) {
added[u] = true;
expand(u);
while (priorityQ.size() > 0) {
connection now = *priorityQ.rbegin();
priorityQ.erase(*priorityQ.rbegin());
deleteEdge(now.a, now.b, now.id);
if (added[now.b] && added[now.a]) {
researchers += now.cost;
}
else if (added[now.b]) {
PrimR(now.a, added);
}
else if (added[now.a]) {
PrimR(now.b, added);
}
}
}
int main()
{
int t;
// loop over all test cases
scanf("%d ", &t);
for (int i = 1; i <= t; i++) {
// read input nodes n, connections m
scanf("%d %d", &n, &m);
adj = new std::list<connection>[n];
//read connections and save them
for (int j = 0; j < m; j++) {
int a, b, c;
scanf("%d %d %d", &a, &b, &c);
addEdge(a - 1, b - 1, c, j);
}
researchers = 0;
// Use of prim with heaviest edges first
bool *added = new bool[n];
for (int j = 0; j < n; j++) {
added[j] = false;
}
for (int j = 0; j < n; j++) {
if (!added[j]) {
Prim(j, added);
}
}
// print desired output
printf("Case #%d: %d\n", i, researchers);
delete[] adj;
delete[] added;
}
return 0;
}
You can use Floyd-Warshall algorithm.
The Floyd-Warshall algorithm finds shortest path between all pairs of vertices.
And this shortest path to (u,u) -> (u,u) is the answer you're finding after considering every possible vertex u.
The algorithm run time is O(n^3).

How to implement a max heap

I have the code to build a max heap, but it keeps on returning the same array I give it. I'm sure its a minor error, but I cant seem to figure it out. Any help is appreciated.
Compilable sample code:
#include <iostream>
#include <cmath>
class Heaparr {
public:
Heaparr();
void insert(int da);
int getLeft(int i) { return 2 * i; }
int getRight(int i) { return (2 * i) + 1; }
int getParent(int i) { return i / 2; }
int getMax() { return maxHeap[0]; }
void print();
void reheap(int num);
void makeArray();
void Build_Max_Heap(int maxHeap[], int heap_size);
void Max_Heapify(int heapArray[], int i, int heap_size);
void heapSort(int heapArray[]);
private:
int size;
int* maxHeap;
int index;
int i;
};
Heaparr::Heaparr() {
maxHeap = nullptr;
size = 0;
}
void Heaparr::insert(int da) {
size++;
int* tmp = new int[size];
for (int i = 0; i < size - 1; i++) {
tmp[i] = maxHeap[i];
}
tmp[size - 1] = da;
delete[] maxHeap;
maxHeap = tmp;
}
void Heaparr::heapSort(int maxHeap[]) {
int heap_size = size;
int n = size;
int temp;
Build_Max_Heap(maxHeap, heap_size);
for (int i = n - 1; i >= 1; i--) {
temp = maxHeap[0];
maxHeap[0] = maxHeap[i];
maxHeap[i] = temp;
heap_size = heap_size - 1;
Max_Heapify(maxHeap, 0, heap_size);
}
for (int i = 0; i < 8; i++) {
std::cout << maxHeap[i] << std::endl;
}
}
void Heaparr::Build_Max_Heap(int maxHeap[], int heap_size) {
int n = size;
for (int i = floor((n - 1) / 2); i >= 0; i--) {
Max_Heapify(maxHeap, i, heap_size);
}
return;
}
void Heaparr::Max_Heapify(int heapArray[], int i, int heap_size) {
// int n = size;
int largest = 0;
int l = getLeft(i);
int r = getRight(i);
if ((l <= heap_size) && (heapArray[l] > heapArray[i])) {
largest = l;
} else {
largest = i;
}
if ((r <= heap_size) && (heapArray[r] > heapArray[largest])) {
largest = r;
}
int temp;
if (largest != i) {
temp = heapArray[i];
heapArray[i] = heapArray[largest];
heapArray[largest] = temp;
Max_Heapify(heapArray, largest, heap_size);
}
return;
}
int main(int argc, char* argv[]) {
int hArray[8] = {5, 99, 32, 4, 1, 12, 15, 8};
Heaparr t;
t.heapSort(hArray);
for (auto v : hArray) {
std::cout << v << ", ";
}
std::cout << std::endl;
}
I made some fixed to the code (i try not to changed much the original code):
The getLeft, getRight and getParent formulas were wrong (ex: when i == 0 children must be 1 and 2 and with your code are 0 and 1. The return type was also wrong, should be int (array index).
Do you receive in all methods a int[] except in insert and the member variable that are double[], changed all to int[], if you need changed back all to double
Using std::swap for swap values in the array.
Adding the length of the array to heapSort (inside the method this info is lost, need to be passed by parameter).
Notes:
I dont see where you use the member variable maxHeap, because all methods except getMax and insert use the array passed by parameter and not the member variable (perhaps you should initialized in the constructor or in heapSort method.
Try to use std::vector instead of C Array
Code:
#include <iostream>
#include <cmath>
class Heaparr {
public:
Heaparr();
void insert(int da);
int getLeft(int i) { return 2 * i + 1; }
int getRight(int i) { return 2 * i + 2; }
int getParent(int i) { return (i - 1) / 2; }
int getMax() { return maxHeap[0]; }
void print();
void reheap(int num);
void makeArray();
void Build_Max_Heap(int heapArray[], int heap_size);
void Max_Heapify(int heapArray[], int i, int heap_size);
void heapSort(int heapArray[], int heap_size);
private:
int size;
int* maxHeap;
int index;
int i;
};
Heaparr::Heaparr() {
maxHeap = nullptr;
size = 0;
}
void Heaparr::insert(int da) {
size++;
int* tmp = new int[size];
for (int i = 0; i < size - 1; i++) {
tmp[i] = maxHeap[i];
}
tmp[size - 1] = da;
delete[] maxHeap;
maxHeap = tmp;
}
void Heaparr::heapSort(int heapArray[], int heap_size) {
size = heap_size;
int n = size;
Build_Max_Heap(heapArray, heap_size);
for (int i = n - 1; i >= 1; i--) {
std::swap(heapArray[0], heapArray[i]);
heap_size = heap_size - 1;
Max_Heapify(heapArray, 0, heap_size);
}
}
void Heaparr::Build_Max_Heap(int heapArray[], int heap_size) {
int n = size;
for (int i = floor((n - 1) / 2); i >= 0; i--) {
Max_Heapify(heapArray, i, heap_size);
}
return;
}
void Heaparr::Max_Heapify(int heapArray[], int i, int heap_size) {
// int n = size;
int largest = 0;
int l = getLeft(i);
int r = getRight(i);
if ((l < heap_size) && (heapArray[l] < heapArray[i])) {
largest = l;
} else {
largest = i;
}
if ((r < heap_size) && (heapArray[r] < heapArray[largest])) {
largest = r;
}
if (largest != i) {
std::swap(heapArray[i], heapArray[largest]);
Max_Heapify(heapArray, largest, heap_size);
}
return;
}
int main(int argc, char* argv[]) {
int hArray[8] = {5, 99, 32, 4, 1, 12, 15, 8};
Heaparr t;
t.heapSort(hArray, sizeof(hArray)/sizeof(hArray[0]));
for (auto v : hArray) {
std::cout << v << ", ";
}
std::cout << std::endl;
return 0;
}
Output:
99, 32, 15, 12, 8, 5, 4, 1,
Tested in GCC 4.9.0 with C++11
If you're willing to consider alternative implementations, then here is one:
#define MIN_TYPE 0
#define MAX_TYPE ~0
template<int TYPE,typename ITEM>
class Heap
{
public:
Heap(int iMaxNumOfItems);
virtual ~Heap();
public:
bool AddItem(ITEM* pItem);
bool GetBest(ITEM** pItem);
protected:
int BestOfTwo(int i,int j);
void SwapItems(int i,int j);
protected:
ITEM** m_aItems;
int m_iMaxNumOfItems;
int m_iCurrNumOfItems;
};
template<int TYPE,typename ITEM>
Heap<TYPE,ITEM>::Heap(int iMaxNumOfItems)
{
m_iCurrNumOfItems = 0;
m_iMaxNumOfItems = iMaxNumOfItems;
m_aItems = new ITEM*[m_iMaxNumOfItems];
if (!m_aItems)
throw "Insufficient Memory";
}
template<int TYPE,typename ITEM>
Heap<TYPE,ITEM>::~Heap()
{
delete[] m_aItems;
}
template<int TYPE,typename ITEM>
bool Heap<TYPE,ITEM>::AddItem(ITEM* pItem)
{
if (m_iCurrNumOfItems == m_iMaxNumOfItems)
return false;
m_aItems[m_iCurrNumOfItems] = pItem;
for (int i=m_iCurrNumOfItems,j=(i+1)/2-1; j>=0; i=j,j=(i+1)/2-1)
{
if (BestOfTwo(i,j) == i)
SwapItems(i,j);
else
break;
}
m_iCurrNumOfItems++;
return true;
}
template<int TYPE,typename ITEM>
bool Heap<TYPE,ITEM>::GetBest(ITEM** pItem)
{
if (m_iCurrNumOfItems == 0)
return false;
m_iCurrNumOfItems--;
*pItem = m_aItems[0];
m_aItems[0] = m_aItems[m_iCurrNumOfItems];
for (int i=0,j=(i+1)*2-1; j<m_iCurrNumOfItems; i=j,j=(i+1)*2-1)
{
if (j+1 < m_iCurrNumOfItems)
j = BestOfTwo(j,j+1);
if (BestOfTwo(i,j) == j)
SwapItems(i,j);
else
break;
}
return true;
}
template<int TYPE,typename ITEM>
int Heap<TYPE,ITEM>::BestOfTwo(int i,int j)
{
switch (TYPE)
{
case MIN_TYPE: return *m_aItems[i]<*m_aItems[j]? i:j;
case MAX_TYPE: return *m_aItems[i]>*m_aItems[j]? i:j;
}
throw "Illegal Type";
}
template<int TYPE,typename ITEM>
void Heap<TYPE,ITEM>::SwapItems(int i,int j)
{
ITEM* pItem = m_aItems[i];
m_aItems[i] = m_aItems[j];
m_aItems[j] = pItem;
}
And here is a usage example:
typedef int ITEM;
#define SIZE 1000
#define RANGE 100
void test()
{
ITEM* pItem;
ITEM aArray[SIZE];
Heap<MIN_TYPE,ITEM> cHeap(SIZE);
srand((unsigned int)time(NULL));
for (int i=0; i<SIZE; i++)
{
aArray[i] = rand()%RANGE;
cHeap.AddItem(aArray+i);
}
for (int i=0; i<SIZE; i++)
{
cHeap.GetBest(&pItem);
printf("%d\n",*pItem);
}
}
Description:
This class stores up to N items of type T
It allows adding an item or extracting the best item
Supported operations are accomplished at O(log(n)), where n is the current number of items
Remarks:
T is determined at declaration and N is determined at initialization
The meaning of "best", either minimal or maximal, is determined at declaration
In order to support Heap<MIN,T> and Heap<MAX,T>, one of the following options must be viable:
bool operator<(T,T) and bool operator>(T,T)
bool T::operator<(T) and bool T::operator>(T)
T::operator P(), where P is a type, for which, one of the above options is viable

Find all possible arrays of size n constructed with all possible combinations of elements from another array in all possible orders?

For an array A of arbitrary length n, I'd like to fill in a n x m array B with all combination of elements from A that includes all possible orders of those elements. For example, if A = {1, 2, 3} and m = 2, I'd like to get B as:
11
12
13
21
22
23
31
32
33
What is an efficient way to do this in C/C++? Thanks!
EDIT: Here is what I figured out to work (data is within the class combs which is basically a matrix class with some added tricks):
void combs::setCombs (int arr[], int n, int m) {
int z, tmp, repeat;
int max = (int (pow(double (n), double( m ))));
for (int i = 0; i < m; i++) {
z = 0;
repeat = int (pow( double (n), double (i)));
for (int j = 0; j < repeat; j++) {
for (int k = 0; k < n; k ++) {
for (int p = 0; p < max/(n*repeat); p ++) {
cout << arr[k] << endl;
data[z*ROWS + i] = arr[k];
z++;
}
}
}
}
}
As mentioned by #Joachim Pileborg your question lacks a lot in the way of parameters.But lets say you could guarantee that you were passing me a vector of SORTED UNIQUE ints. Then this brute force would be possible:
std::vector< std::string > Combo( const std::vector< char >& source, int m )
{
std::vector< std::vector< char >::const_iterator > digits( length, source.cbegin() );
std::vector< std::string > result( source.size() * m );
for( int i = 0; i < result.size(); i++ )
{
for( int j = 0; j < m; j++ )
{
result[i] += *(digits[j]);
}
for( int j = digits.size() - 1; j >= 0; j-- )
{
++digits[j];
if( digits[j] == source.cend() )
{
digits[j] = source.cbegin();
}
else
{
break;
}
}
}
return result;
}
What you are describing sounds like partial permutations, not combinations.
If you are using c++, then it is recommended to use vectors, because vectors can tell you their size, and they free their own memory. An implementation with vectors would be as follows:
vector<vector<int> > partialPermutations(vector<int> &A,int m){
int i,i2,t,n=A.size(),total=1;
for(i=0;i<m;i++) total*=n;
vector<vector<int> > result;
for(i=0;i<total;i++){
result.push_back(vector<int>());
t=i;
for(i2=0;i2<m;i2++){
result[i].push_back(A[t%n]);
t/=n;
}
}
return result;
}
int main() {
vector<int> A;
int total,i,i2;
for(i=1;i<=4;i++) A.push_back(i);
vector<vector<int> > re=partialPermutations(A,2);
for(i=0;i<re.size();i++){
for(i2=0;i2<2;i2++)
cout<<re[i][i2]<<" ";
cout<<endl;
}
return 0;
}
If you still want to use arrays, then the code would be as follows:
int** partialPermutations(int*A,int n,int m,int &total){
int i,i2,t;
total=1;
for(i=0;i<m;i++) total*=n;
int **result=new int*[total];
for(i=0;i<total;i++){
t=i;
result[i]=new int[m];
for(i2=0;i2<m;i2++){
result[i][i2]=A[t%n];
t/=n;
}
}
return result;
}
int main() {
int A[]={1,2,3,4};
int total,i,i2;
int **re=partialPermutations(A,4,2,total);
for(i=0;i<total;i++){
for(i2=0;i2<2;i2++)
cout<<re[i][i2]<<" ";
cout<<endl;
}
//Cleanup
for(i=0;i<total;i++) delete[] re[i];
delete[] re;
return 0;
}
Notice that by using arrays, we have to recover the size of the resulting array (passing total by reference), and we have to free the memory afterwards. None of this is needed with vectors.
#include<iostream>
using namespace std;
void printStrRec(string s,string ans,int k,int i)
{
if(i==k)
{
cout<<"\nAnswer : "<<ans<<endl;
}
else
{
for(int x=0;x<s.size();++x)
{
ans[i]=s[x];
printStrRec(s,ans,k,i+1);
}
}
}
void printStrings(string s,int k)
{
string ans;
for(int p=0;p<k;++p)
{
ans+="x";
}
printStrRec(s,ans,k,0);
}
int main()
{
int k;
string s;
cout<<"Enter the set : ";
cin>>s;
cout<<"\nEnter k : ";
cin>>k;
printStrings(s,k);
return 0;
}
Hope that helps.