Related
I would like to build a C++ program that show all the possible combinations depending on the number of elements taken by a N factor.
Let's suppose a vector vec[6] with elements 1 2 3 4 5 6 on it.
Using the combination formula, 6! / 4! (6 - 4)! = 15 possibilities
I want to generate a function which gives the result of all 15 possibilities taken 4 by 4 with no repetition, as example:
1 2 3 4
1 2 3 5
1 2 3 6
2 3 4 5
and so on...
I am using this code for now, but i want to use numbers from my vector (v[6]).
#include <algorithm>
#include <iostream>
#include <string>
void comb(int N, int K)
{
std::string bitmask(K, 1); // K leading 1's
bitmask.resize(N, 0); // N-K trailing 0's
// print integers and permute bitmask
do {
for (int i = 0; i < N; ++i) // [0..N-1] integers
{
if (bitmask[i]) std::cout << " " << i;
}
std::cout << std::endl;
} while (std::prev_permutation(bitmask.begin(), bitmask.end()));
}
int main()
{
comb(6, 4);
}
Would you please guys give me a help? I'd like to know where i could change the code so that i can use my own vector.
i'm generating this vector v[i] and sorting it with a bubble sort, like this:
void order (int d[], int n){
int i, j;
for (i = 1; i < n; i++)
for (j = 0; j < n-1; j++)
if (d[j] > d[j+1])
swap (d[j],d[j+1]);
for (i = 0; i < n; i++)
cout << d[i] << " ";
}
after that sorting, i want to put my vector into the comb function.
how could i make it is possible?
Here's a C++14 solution that uses a free, open source library to do the work:
#include "combinations"
#include <iomanip>
#include <iostream>
#include <vector>
int
main()
{
std::vector<int> v{1, 2, 3, 4, 5, 6};
int state = 0;
for_each_combination(v.begin(), v.begin() + 4, v.end(),
[&state](auto first, auto last)
{
std::cout << std::setw(2) << ++state << " : ";
while (true)
{
std::cout << *first;
if (++first == last)
break;
std::cout << ' ';
}
std::cout << '\n';
return false;
});
}
This outputs:
1 : 1 2 3 4
2 : 1 2 3 5
3 : 1 2 3 6
4 : 1 2 4 5
5 : 1 2 4 6
6 : 1 2 5 6
7 : 1 3 4 5
8 : 1 3 4 6
9 : 1 3 5 6
10 : 1 4 5 6
11 : 2 3 4 5
12 : 2 3 4 6
13 : 2 3 5 6
14 : 2 4 5 6
15 : 3 4 5 6
The source code for the library can be copy/pasted from the above link and inspected for how it works. This library is extremely high performance compared to solutions using std::prev_permutation. The implementation is relatively simple for this function, but the library also contains more functionality that grows increasingly complicated to implement (but just as easy to use):
template <class BidirIter, class Function>
Function
for_each_combination(BidirIter first,
BidirIter mid,
BidirIter last,
Function f);
template <class BidirIter, class Function>
Function
for_each_permutation(BidirIter first,
BidirIter mid,
BidirIter last,
Function f);
template <class BidirIter, class Function>
Function
for_each_reversible_permutation(BidirIter first,
BidirIter mid,
BidirIter last,
Function f);
template <class BidirIter, class Function>
Function
for_each_circular_permutation(BidirIter first,
BidirIter mid,
BidirIter last,
Function f);
template <class BidirIter, class Function>
Function
for_each_reversible_circular_permutation(BidirIter first,
BidirIter mid,
BidirIter last,
Function f);
The library has several pleasant features including:
Your input sequence (vector or whatever) need not be sorted.
You can prematurely break out of the loop at any time by returning true.
If you don't break out of the loop early, the sequence is always returned to its original state.
The functor always receives iterators to the first k elements of the sequence, so it is possible to also operate on the elements not selected if you tell the functor about the total length of the sequence.
Feel free to use the library as is, or study and take what you need from its implementation. The link above contains a tutorial-like description, and a detailed specification of each function.
Start with subset S = {1,2,3,...,k}, that's the first subset. Generate the next subset by examining elements from the right (start with the last), and increment it if you can (if it is < N), and return that as the next subset. If you can't increment it, look at the element to the left until you find one you can increment. Increment it, and set the elements to the right sequentially from that point. Below are the 3 element subsets of {1,2,3,4,5} (N=5,k=3,there are 10 subsets):
{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>
#include <vector>
std::ostream& operator<<(std::ostream& o, std::vector<int>& a)
{
o << "{";
for (std::vector<int>::const_iterator it = a.begin(); it != a.end(); ++it) {
o << *it;
if (it + 1 < a.end()) o << ",";
}
return o << "}";
}
int main()
{
const int N = 7;
const int k = 4;
std::vector<int> A(k);
// initialize
for (int i = 0; i < k; ++i) {
A[i] = i + 1;
}
std::cout << A << std::endl;
int h = 0;
bool done = false;
do {
++A[k-h-1];
for (int t = k - h; t < k; ++t) {
A[t] = A[t-1] + 1;
}
if (A[k-h-1] < N - h) {
// last element can be incremented, stay there...
h = 0;
} else {
// last element at max, look back ...
++h;
}
done = (A[0] == N - k + 1);
std::cout << A << std::endl;
} while (!done);
}
Pretty simple recursive implementation:
struct Combs
{
vector<int> scombs;
template <typename F>
void call_combs(int n, int k, F f)
{
if (k == 0) {
f();
}
else {
scombs.push_back(n - 1);
call_combs(n - 1, k - 1, f);
scombs.resize(scombs.size() - 1);
if (k < n) {
call_combs(n - 1, k, f);
}
}
}
};
...
Combs combs;
const auto& coco = combs.scombs;
combs.call_combs(6, 4, [&coco](){
copy(coco.cbegin(), coco.cend(), ostream_iterator<int>(cout));
cout << endl;
});
I need an algorithm that, given an even number of elements, performs an evaluation on all combinations of the elements divided into two groups. Order within a group doesn't matter and so permutations within groups shouldn't be repeated. An example with N=4 elements would be the evaluations
e(12,34), e(13,24), e(14,32), e(32,14), e(34,12), e(24,13)
I thought I had it, with a recursive algorithm that works up to N=6, but it turns out it fails for N=8. This is the algorithm (this version just prints out the two groups; in my actual implementation it will perform a calculation):
// Class for testing algoritm
class sym {
private:
int N, Nhalf, combs;
VI order;
void evaluate();
void flip(int, int);
void combinations(int, int);
public:
void combinations();
sym(int N_) : N(N_) {
if(N%2) {
cout "Number of particles must divide the 2 groups; requested N = " << N << endl;
throw exception();
}
Nhalf=N/2;
order.resize(N);
for(int i=0;i<N;i++) order[i]=i+1;
}
~sym() {
cout << endl << combs << " combinations" << endl << endl;
}
};
// Swaps element n in group 1 and i in group 2
void sym::flip(int n, int i) {
int tmp=order[n];
order[n]=order[i+Nhalf];
order[i+Nhalf]=tmp;
}
// Evaluation (just prints the two groups)
void sym::evaluate() {
for(int i=0;i<Nhalf;i++) cout << order[i] << " ";
cout << endl;
for(int i=Nhalf;i<N;i++) cout << order[i] << " ";
cout << endl << "--------------------" << endl;
combs++;
}
// Starts the algorithm
void sym::combinations() {
cout << "--------------------" << endl;
combinations(0, 0);
}
// Recursive algorithm for the combinations
void sym::combinations(int n, int k) {
if(n==Nhalf-1) {
evaluate();
for(int i=k;i<Nhalf;i++) {
flip(n, i);
evaluate();
flip(n, i);
}
return;
}
combinations(n+1, k);
for(int i=k;i<Nhalf;i++) {
flip(n, i);
combinations(n+1, k+i+1);
flip(n, i);
}
}
If I run this with N=2 for example, I get the correct
--------------------
1 2
3 4
--------------------
1 3
2 4
--------------------
1 4
3 2
--------------------
3 2
1 4
--------------------
3 4
1 2
--------------------
4 2
3 1
--------------------
6 combinations
But it seems N>6 doesn't work. Is there a simple change that will fix this, or will I have to rethink the whole thing?
EDIT: It is better if every change just involves swapping two elements (like the failed attempt above); as this will make the code faster in the end I think.
EDIT: Just realised it fails for N=6 as well, sloppy testing.
std::next_permutation may help (without recursion):
#include <iostream>
#include <algorithm>
template<typename T>
void do_job(const std::vector<T>& v, const std::vector<std::size_t>& groups)
{
std::cout << " e(";
for (std::size_t i = 0; i != v.size(); ++i) {
if (groups[i] == 0) {
std::cout << " " << v[i];
}
}
std::cout << ",";
for (std::size_t i = 0; i != v.size(); ++i) {
if (groups[i] == 1) {
std::cout << " " << v[i];
}
}
std::cout << ")\n";
}
template<typename T>
void print_combinations(const std::vector<T>& v)
{
std::vector<std::size_t> groups(v.size() / 2, 0);
groups.resize(v.size(), 1); // groups is now {0, .., 0, 1, .., 1}
do {
do_job(v, groups);
} while (std::next_permutation(groups.begin(), groups.end()));
}
int main()
{
std::vector<int> numbers = {1, 2, 3, 4};
print_combinations(numbers);
}
Live Demo
// generate all combination that use n of the numbers 1..k
void sym::combinations(int n, int k) {
if (n>k) return; // oops
if (n==0) { evaluate(); return; }
combinations(n, k-1);
order[n-1] = k;
combinations(n-1,k-1);
}
Start that with combinations(N/2,N) No need to pre initialize order. But as coded it only fills the first half of order with the first group and you need to post process to get the second group.
With a moderate amount of extra logic, you could instead fill in the second half during combinations. I think this does it:
void sym::combinations(int n, int k) {
if (k==0) { evaluate(); return; }
if (n>0) {
order[n-1] = k;
combinations(n-1,k-1); }
if (n<k) {
order[Nhalf+k-n-1] = k;
combinations(n, k-1); }
}
I think a flip based design is uglier. But after more thought, it isn't actually difficult. So changing back to your design of starting at combinations(0,0) you could use:
// Generate all combinations subject to having already filled the first n
// of the first group and having already filled the last k of the second.
void sym::combinations(int n, int k) {
if(n==Nhalf) {
// Once the first group is full, the rest must be the second group
evaluate();
return;
}
// Since the first group isn't full, recursively get all combinations
// That make the current order[n] part of the first group
combinations(n+1,k);
if (k<Nhalf) {
// Next try all combinations that make the current order[n] part of
// the second group
std::swap(order[n], order[N-k-1]);
combinations(n,k+1);
// Since no one cares about the sequence of the items not yet chosen
// there is no benefit to swapping back.
}
}
To recursively list the n choose n/2 combinations you could use an algorithm that adds each value to either group:
f(n,k,A,B):
if k == 0:
output A,B with {n,n-1..1}
else if n == k:
output A with {n,n-1..1},B
else if k > 0:
f(n-1,k-1,A with n,B)
f(n-1,k,A,B with n)
Example below. To half the accumulating stack, one could skip one of the two first recursive calls and reverse the order of the pair during evaluation.
f(4,2,[],[])
f(3,1,[4],[])
f(2,0,[4,3],[]) => {[4,3],[2,1]}
f(2,1,[4],[3])
f(1,0,[4,2],[3]) => {[4,2],[3,1]}
f(1,1,[4],[3,2]) => {[4,1],[3,2]}
f(3,2,[],[4])
f(2,1,[3],[4])
f(1,0,[3,2],[4]) => {[3,2],[4,1]}
f(1,1,[3],[4,2]) => {[3,1],[4,2]}
f(2,2,[],[4,3]) => {[2,1],[4,3]}
I need a different version of permutations for my code. I could able to achieve what I want but it is not generic enough. my algorithm keeps going bigger along with my requirements. But that should not be.
This is not a home work for any one, I need it for one my critical projects, wondering if any pre-defined algorithms available from boost or any other.
Below is the standard version of next_permutation using c++.
// next_permutation example
#include <iostream> // std::cout
#include <algorithm> // std::next_permutation
int main ()
{
int myints[] = {1,2,3};
do
{
std::cout << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n';
} while ( std::next_permutation(myints,myints+3) );
return 0;
}
That gives below output :
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
But my requirement is :- Let's say I have 1 to 9 numbers :
1,2,3,4,5,6,7,8,9
And I need a variable length of permutations and in only ASCENDING order and with out DUPLICATES.
Let's say i need 3 digit length of permutations then i need output as below.
123
124
125
.
.
.
128
129
134 // After 129 next one should be exactly 134
135 // ascending order mandatory
136
.
.
.
148
149
156 // exactly 156 after 149, ascending order mandatory
.
.
.
489 // exactly 567 after 489, because after 3rd digit 9, 2nd digit
567 // will be increased to 49? , so there is no possibility for
. // 3rd digit, so first digit gets incremented to 5 then 6 then
. // 7, in ascending order.
.
.
.
789 // and this should be the last set I need.
My list may contain upto couple of hundred's of numbers and variable length can be 1 to up to Size of the list.
My own algorithm is working for specific variable length, and a specific size, when they both changes, i need to write huge code. so, looking for a generic one.
I am not even sure if this is called as Permutations or there is a different name available for this kind of math/logic.
Thanks in advance.
musk's
Formally, you want to generate all m-combinations of the set [0;n-1].
#include <iostream>
#include <vector>
bool first_combination (std::vector<int> &v, int m, int n)
{
if ((m < 0) || (m > n)) {
return false;
}
v.clear ();
v.resize (m);
for (int i = 0; i < m; i++) {
v[i] = i;
}
return true;
}
bool next_combination (std::vector<int> &v, int m, int n)
{
for (int i = m - 1; i >= 0; i--) {
if (v[i] + m - i < n) {
v[i]++;
for (int j = i + 1; j < m; j++) {
v[j] = v[j - 1] + 1;
}
return true;
}
}
return false;
}
void print_combination (const std::vector<int> &v)
{
for (size_t i = 0; i < v.size(); i++) {
std::cout << v[i] << ' ';
}
std::cout << '\n';
}
int main ()
{
const int m = 3;
const int n = 5;
std::vector<int> v;
if (first_combination (v, m, n)) {
do {
print_combination (v);
} while (next_combination (v, m, n));
}
}
You can use this code and the linked article as inspiration.
This task can be done with a simple iterative algorithm. Just increment the first element that can be incremented and rescale the elements before it until there is no element to be incremented.
int a[] = {0,1,2,3,4,5,6,7,8,9}; // elements: must be ascending in this case
int n = sizeof(a)/sizeof(int);
int digits = 7; // number of elements you want to choose
vector<int> indexes; // creating the first combination
for ( int i=digits-1;i>=0;--i ){
indexes.push_back(i);
}
while (1){
/// printing the current combination
for ( int i=indexes.size()-1;i>=0;--i ){
cout << a[indexes[i]] ;
} cout << endl;
///
int i = 0;
while ( i < indexes.size() && indexes[i] == n-1-i ) // finding the first element
++i; // that can be incremented
if ( i==indexes.size() ) // if no element can be incremented, we are done
break;
indexes[i]++; // increment the first element
for ( int j=0;j<i;++j ){ // rescale elements before it to first combination
indexes[j] = indexes[i]+(i-j);
}
}
Output:
0123456
0123457
0123458
0123459
0123467
0123468
0123469
0123478
0123479
0123489
0123567
0123568
0123569
0123578
0123579
0123589
0123678
0123679
0123689
0123789
0124567
0124568
0124569
0124578
0124579
0124589
0124678
0124679
0124689
0124789
0125678
0125679
0125689
0125789
0126789
0134567
0134568
0134569
0134578
0134579
0134589
0134678
0134679
0134689
0134789
0135678
0135679
0135689
0135789
0136789
0145678
0145679
0145689
0145789
0146789
0156789
0234567
0234568
0234569
0234578
0234579
0234589
0234678
0234679
0234689
0234789
0235678
0235679
0235689
0235789
0236789
0245678
0245679
0245689
0245789
0246789
0256789
0345678
0345679
0345689
0345789
0346789
0356789
0456789
1234567
1234568
1234569
1234578
1234579
1234589
1234678
1234679
1234689
1234789
1235678
1235679
1235689
1235789
1236789
1245678
1245679
1245689
1245789
1246789
1256789
1345678
1345679
1345689
1345789
1346789
1356789
1456789
2345678
2345679
2345689
2345789
2346789
2356789
2456789
3456789
I have written a graph structure as an edge list, and am trying to write Kruskal's MST algorithm for it.
Here's my code so far:
#include <bits/stdc++.h>
using namespace std;
struct _ { ios_base::Init i; _() { cin.sync_with_stdio(0); cin.tie(0); } } _;
//////////////////////////////////////////////////////////////////////////////////
#define endl '\n'
#define ll long long
#define pb push_back
#define mt make_tuple
#define in(a) for (auto& i: a)
//////////////////////////////////////////////////////////////////////////////////
#define edge tuple < ll, ll, ll >
bool func (edge a, edge b) { return get<2>(a) < get<2>(b); }
struct graph
{
ll v;
vector <edge> edgelist;
void addedge (edge x) { edgelist.pb(x); }
ll find (vector <ll> parent, ll i)
{ return parent[i]==-1 ? i : find (parent, parent[i]); }
bool cycle()
{
vector <ll> parent (v);
fill (parent.begin(), parent.end(), -1);
in (edgelist)
{
ll x = find (parent, get<0>(i));
ll y = find (parent, get<1>(i));
if (x==y) return true;
else parent[x]=y;
}
return false;
}
graph mst()
{
sort (edgelist.begin(), edgelist.end(), func);
graph tree;
in(edgelist)
{
graph temp = tree;
temp.addedge(i);
if (!temp.cycle()) tree=temp;
}
return tree;
}
};
int main()
{
graph g;
cin >> g.v;
ll e;
cin >> e;
for (ll i=1; i<=e; i++)
{
ll a, b, w;
cin >> a >> b >> w;
g.addedge(mt(a, b, w));
}
graph mstree = g.mst();
in(mstree.edgelist) cout << get<0>(i) << " " << get<1>(i) << " " << get<2>(i) << endl;
cout << endl;
}
/*
Sample Input
4 5
0 1 10
0 2 6
0 3 5
1 3 15
2 3 4
Sample Output
2 3 4
0 3 5
0 1 10
*/
My code takes a very long time to produce the output. Are there any problems in my implementation? Also, if I loop this task for multiple graphs, my program crashes in the middle of execution.
My code takes a very long time to produce the output. Are there any
problems in my implementation?
There are several problems:
First,
ll find (vector <ll> parent, ll i)
{ return parent[i]==-1 ? i : find (parent, parent[i]); }
You pass the parent by value, this means copying all the array. Pass by reference (and non-const, as you will need to modify it, see point 3).
Second, in cycle() you do not need to check all edges, you need to check only the edge that is under consideration in the main loop (in mst()). (And do not set parent in cycle(), you need to use the same array in all mst().)
Third, read on "enhancements" of disjoin-set structure (even the Wikipedia article has it all explained), namely union by rank and path compression. Only with those you will achieve expected performance from the disjoin-set.
Also, if I loop this task for multiple graphs, my program crashes in
the middle of execution.
It is impossible to tell not knowing how to you loop and what are the multiple graphs inputs you are using. However, I strongly suspect stack overflow on even medium-sized graphs as you pass parent by value, thus quickly consuming the stack.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
List List:: mergesort(List m)
{
if(m.count() <= 1)
return m;
else
{
List l,r;
node* temp = m.head;
node* ptemp = m.head;
node* first = m.head;
int c = m.count();
for(int i = 1; temp->next!=NULL && i<=(c/2)+1; i++)
{
ptemp = temp;
temp = temp->next;
}
ptemp->next = NULL;
while(first!=NULL)
{
l.insert(first->data);
first = first->next;
}
while(temp!=NULL)
{
r.insert(temp->data);
temp = temp->next;
}
cout<<"\t\t";
l.display();
cout<<"\t\t";r.display();cout<<"\n";
l = mergesort(l);
r = mergesort(r);
}
}
I am trying to show each step during the 'divide step of merge sort algorithm.
For example I input this List : 5 3 7 14 2
Desired Output :-
5 3 7 14 2
5 3 7 14 2
5 3 7 14 2
5 3 7 14 2
what I get is :
5 3 7 14 2
5 3 7 14 2
5 3 7
5 3
14 2
What should I do? I have tried every possible thing, but can't even get close.
Can Any body help, please?
okay this is what i Understand after debugging,
Whats going inside the function mergesort() is:
mergesort(5 3 7 14 2)
mergesort(5 3 7)
mergesort(5 3)
mergesort(14 2)
What i need is :-
mergesort(5 3 7 14 2)
mergesort(5 3 7)
mergesort(14 2)
mergesort(5 3)
I can't think of anything. Help please.
You are laying the tree out wrongly. You will never get the 'mergesort tree' displayed like that because you cannot move upwards in console output. Instead you should rotate the tree through 90 degrees. Like this
List List:: mergesort(List m, int depth)
{
for (int i = 0; i < depth; ++i)
cout << '\t';
display();
cout << '\n';
...
l = mergesort(l, depth + 1);
r = mergesort(r, depth + 1);
}
The depth variable controls how much indentation you display before displaying the values you are sorting on this call. Each call's values are displayed on a separate line. This rotates the tree through 90 degrees, so that the root is displayed on the left edge of your console, with child nodes following their parents and progressively further to the right.
The way I would attempt to create a tree like the one you describe (although not exactly identical because mergesort() doesn't create another level for a one element sequence) is to build up a tree of intermediate states and then use a Breadth-First Search walk of the tree to actually display it. Alternative to actually building the tree as a separate data structure you could implement the mergesort() to not use recursion but to control the intermediate steps yourself, effectively using a Breadth-First Search walk of the implicit tree.
Below is an example of what I mean. The output isn't formatted nicely but, at least, each line contains the expected content. Also, the output shows the intermediate results of both the splitting and the intermediate merges.
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
using namespace std::placeholders;
typedef std::vector<int> range;
std::ostream& print_range(std::ostream& out, range const& v)
{
out << '[';
if (!v.empty()) {
std::copy(v.begin(), v.end() - 1,
std::ostream_iterator<int>(out, ", "));
out << v.back();
}
return out << "] ";
}
std::vector<range>
mergesort(std::vector<range> const& rs)
{
std::cout << "> ";
std::for_each(rs.begin(), rs.end(),
[](range const& r) { print_range(std::cout, r); });
std::cout << "\n";
if (rs.end() != std::find_if(rs.begin(), rs.end(),
[](range const& r) {
return 1 < r.size();
})) {
std::vector<range> sr;
std::for_each(rs.begin(), rs.end(),
[&](range const& r) {
sr.push_back(range(r.begin(),
r.begin() + r.size() / 2));
sr.push_back(range(r.begin() + r.size() / 2,
r.end()));
});
sr = mergesort(sr);
std::vector<range> result;
for (range::size_type i(0); i + 1 < sr.size(); i += 2) {
result.push_back(range());
std::merge(sr[i].begin(), sr[i].end(),
sr[i + 1].begin(), sr[i + 1].end(),
std::back_inserter(result.back()));
}
std::cout << "< ";
std::for_each(result.begin(), result.end(),
[](range const& r) { print_range(std::cout, r); });
std::cout << "\n";
return result;
}
else {
return rs;
}
}
range mergesort(range const& input)
{
return mergesort(std::vector<range>(1, input)).front();
}
int main()
{
try
{
range input{std::istream_iterator<int>(std::cin),
std::istream_iterator<int>()};
mergesort(input);
}
catch (std::exception const& ex)
{
std::cout << "ERROR: " << ex.what() << '\n';
}
}