How can I make an algorithm in C++ for finding variations of a set without repetition (i.e. n elements,...
How to approximate rolls for potions of healing using only d6's?
Activating a Alphanet Faucet Wallet Remotely (without tezos-client)
Is my plan for fixing my water heater leak bad?
What is the purpose of easy combat scenarios that don't need resource expenditure?
ip vs ifconfig commands pros and cons
Which branches of mathematics can be done just in terms of morphisms and composition?
What is the wife of a henpecked husband called?
It took me a lot of time to make this, pls like. (YouTube Comments #1)
I am on the US no-fly list. What can I do in order to be allowed on flights which go through US airspace?
How do Japanese speakers determine the implied topic when none has been mentioned?
Finding ratio of the area of triangles
How should I state my MS degree in my CV when it was in practice a joint-program?
Should I choose Itemized or Standard deduction?
How do I add a variable to this curl command?
Word to be used for "standing with your toes pointing out"
Walking in a rotating spacecraft and Newton's 3rd Law of Motion
Why is this code uniquely decodable?
Why is working on the same position for more than 15 years not a red flag?
What are these green text/line displays shown during the livestream of Crew Dragon's approach to dock with the ISS?
Why is my solution for the partial pressures of two different gases incorrect?
How to prepare vegetables for a sandwich that can last for several days in a fridge?
How to satisfy a player character's curiosity about another player character?
Avoiding morning and evening handshakes
Why is c4 a better move in this position?
How can I make an algorithm in C++ for finding variations of a set without repetition (i.e. n elements, choose k)?
How can I profile C++ code running on Linux?What algorithms compute directions from point A to point B on a map?How can I get the list of files in a directory using C or C++?what are the fast algorithms to find duplicate elements in a collection and group them?defining < operator for map of list iteratorsC++ : push_back a map<string, int> into a vector<map<string, int> > via an iterator?How to find time complexity of an algorithmHow to implement classic sorting algorithms in modern C++?use std::find to find a std::tuple in a std::vectorHow can one populate a vector with all possible string combinations of n vector length in the C++ programming language
For example, (n = 3, k = 2)
, I have set {1, 2, 3}
and I need my algorithm to find:
{1, 2}, {1, 3}, {2, 1}, {2, 3}, {3, 1}, {3, 2}
.
I was able to make an algorithm with next_permutation
, but it works very slow for n = 10, k = 4
(which is what I need).
Here's my code:
#include <iostream>
#include <algorithm>
#define pb push_back
using namespace std;
int main() {
vector <int> s = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int k = 4; // (n = 10, k = 4)
map <string, int> m; // To check if we already have that variation
vector <string> v; // Variations
do {
string str = "";
for (int i = 0; i < k; i++) str += to_string(s[i]);
if (m[str] == 0) {
m[str] = 1;
v.pb(str);
}
} while (next_permutation(s.begin(), s.end()));
return 0;
}
How can I make an algorithm that does this faster?
c++ algorithm permutation
add a comment |
For example, (n = 3, k = 2)
, I have set {1, 2, 3}
and I need my algorithm to find:
{1, 2}, {1, 3}, {2, 1}, {2, 3}, {3, 1}, {3, 2}
.
I was able to make an algorithm with next_permutation
, but it works very slow for n = 10, k = 4
(which is what I need).
Here's my code:
#include <iostream>
#include <algorithm>
#define pb push_back
using namespace std;
int main() {
vector <int> s = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int k = 4; // (n = 10, k = 4)
map <string, int> m; // To check if we already have that variation
vector <string> v; // Variations
do {
string str = "";
for (int i = 0; i < k; i++) str += to_string(s[i]);
if (m[str] == 0) {
m[str] = 1;
v.pb(str);
}
} while (next_permutation(s.begin(), s.end()));
return 0;
}
How can I make an algorithm that does this faster?
c++ algorithm permutation
1
You might usenext_permutation
on abitset
(of size n, with k true). bitset shows valid item from thevector
.
– Jarod42
12 hours ago
@Jarod42 how do I usenext_permutation
onbitset
? I can't find how to.
– Pero
11 hours ago
add a comment |
For example, (n = 3, k = 2)
, I have set {1, 2, 3}
and I need my algorithm to find:
{1, 2}, {1, 3}, {2, 1}, {2, 3}, {3, 1}, {3, 2}
.
I was able to make an algorithm with next_permutation
, but it works very slow for n = 10, k = 4
(which is what I need).
Here's my code:
#include <iostream>
#include <algorithm>
#define pb push_back
using namespace std;
int main() {
vector <int> s = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int k = 4; // (n = 10, k = 4)
map <string, int> m; // To check if we already have that variation
vector <string> v; // Variations
do {
string str = "";
for (int i = 0; i < k; i++) str += to_string(s[i]);
if (m[str] == 0) {
m[str] = 1;
v.pb(str);
}
} while (next_permutation(s.begin(), s.end()));
return 0;
}
How can I make an algorithm that does this faster?
c++ algorithm permutation
For example, (n = 3, k = 2)
, I have set {1, 2, 3}
and I need my algorithm to find:
{1, 2}, {1, 3}, {2, 1}, {2, 3}, {3, 1}, {3, 2}
.
I was able to make an algorithm with next_permutation
, but it works very slow for n = 10, k = 4
(which is what I need).
Here's my code:
#include <iostream>
#include <algorithm>
#define pb push_back
using namespace std;
int main() {
vector <int> s = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int k = 4; // (n = 10, k = 4)
map <string, int> m; // To check if we already have that variation
vector <string> v; // Variations
do {
string str = "";
for (int i = 0; i < k; i++) str += to_string(s[i]);
if (m[str] == 0) {
m[str] = 1;
v.pb(str);
}
} while (next_permutation(s.begin(), s.end()));
return 0;
}
How can I make an algorithm that does this faster?
c++ algorithm permutation
c++ algorithm permutation
edited 30 mins ago
Peter Mortensen
13.7k1986112
13.7k1986112
asked 12 hours ago
PeroPero
456
456
1
You might usenext_permutation
on abitset
(of size n, with k true). bitset shows valid item from thevector
.
– Jarod42
12 hours ago
@Jarod42 how do I usenext_permutation
onbitset
? I can't find how to.
– Pero
11 hours ago
add a comment |
1
You might usenext_permutation
on abitset
(of size n, with k true). bitset shows valid item from thevector
.
– Jarod42
12 hours ago
@Jarod42 how do I usenext_permutation
onbitset
? I can't find how to.
– Pero
11 hours ago
1
1
You might use
next_permutation
on a bitset
(of size n, with k true). bitset shows valid item from the vector
.– Jarod42
12 hours ago
You might use
next_permutation
on a bitset
(of size n, with k true). bitset shows valid item from the vector
.– Jarod42
12 hours ago
@Jarod42 how do I use
next_permutation
on bitset
? I can't find how to.– Pero
11 hours ago
@Jarod42 how do I use
next_permutation
on bitset
? I can't find how to.– Pero
11 hours ago
add a comment |
4 Answers
4
active
oldest
votes
This code generates arrangements of k items from n in lexicographic order, packed into integer for simplicity (so 153 corresponds to (1,5,3))
void GenArrangement(int n, int k, int idx, int used, int arran) {
if (idx == k) {
std::cout << arran << std::endl;
return;
}
for (int i = 0; i < n; i++)
if (0 == (used & (1 << i)))
GenArrangement(n, k, idx + 1, used | (1 << i), arran * 10 + (i + 1));
}
int main()
{
GenArrangement(5, 3, 0, 0, 0);
}
123
124
125
132
134
135
142
143
145
152
153
154
213
214
215
231
234
235
241
243
245
251
253
254
312
314
315
321
324
325
341
342
345
351
352
354
412
413
415
421
423
425
431
432
435
451
452
453
512
513
514
521
523
524
531
532
534
541
542
543
add a comment |
You can iterate over every subset with a bitmask.
for(unsigned int i = 0; i < (1<<10);i++)
When you do not need portable code you could use
__builtin_popcount(int)
To get the number of 1s in the binary representation at least in gcc with an x86 processor.
for(unsigned int i = 0; i < (1<<10);i++) {
if(__builtin_popcount(i) == 4) { //Check if this subset contains exactly 4 elements
std::string s;
for(int j = 0; j < 10; j++) {
if(i&(1<<j)) { //Check if the bit on the j`th is a one
s.push_back(to_string(j));
}
}
v.push_back(s);
}
}
I am aware of this, but this prints combinations, rather than variations, which is not what I need.
– Pero
11 hours ago
no need to use popcnt, you can use normal slower way of counting en.wikichip.org/wiki/population_count
– NoSenseEtAl
11 hours ago
@Pero when you have the combinations, you can use next permutation on these (which are much smaller)
– Unlikus
11 hours ago
add a comment |
The slowness is due to generating all n! permutations, even when only a fraction of them is required. Your complexity is around O(n! * k log n), where O(k log n) is an upper bound on the complexity to query the std::map
with all of the permutations.
The answer by MBo is limited to 9 values (1..9). Even if it is extended to printing longer values, they are still limited by number of bits (usually 31 for int, and 64 bit if uint64_t is available).
Here it is:
void print_permutations_impl(std::ostream & out, std::vector<int> & values,
unsigned k, std::vector<int> & permutation_stack)
{
if (k == permutation_stack.size())
{
const char* prefix = "";
for (auto elem: permutation_stack) {
out << prefix << elem;
prefix = ", ";
}
out << 'n';
return;
}
auto end_valid = values.size() - permutation_stack.size();
permutation_stack.push_back(0);
for (unsigned i=0 ; i < end_valid; ++i) {
permutation_stack.back() = values[i];
std::swap(values[i], values[end_valid - 1]);
print_permutations_impl(out, values, k, permutation_stack);
std::swap(values[i], values[end_valid - 1]);
}
permutation_stack.pop_back();
}
void print_permutations(std::ostream & out, const std::vector<int> & values, int k)
{
std::vector<int> unique = values;
std::sort(unique.begin(), unique.end());
unique.erase(std::unique(unique.begin(), unique.end()),
unique.end());
std::vector<int> current_permutation;
print_permutations_impl(out, unique, k, current_permutation);
}
It works in sub-second speed for N=100 and K=2.
add a comment |
//finds permutations of an array
#include<iostream>
#include<vector>
using namespace std;
inline void vec_in(vector<unsigned>&, unsigned&);
inline void vec_out(vector<unsigned>&);
inline void vec_sub(vector<vector<unsigned>>&, vector<unsigned>&, unsigned&);
int main(){
unsigned size;
cout<<"SIZE : ";
cin>>size;
vector<unsigned> vec;
vec_in(vec,size);
unsigned choose;
cout<<"CHOOSE : ";
cin>>choose;
vector<vector<unsigned>> sub;
vec_sub(sub, vec, choose);
size=sub.size();
for(unsigned y=0; y<size-2; y++){
for(unsigned j=0; j<choose-1; j++){
vector<unsigned> temp;
for(unsigned i=0; i<=j; i++){
temp.push_back(sub[y][i]);
}
for(unsigned x=y+1; x<size; x++){
if(temp[0]==sub[x][choose-1]){break;}
vector<unsigned> _temp;
_temp=temp;
for(unsigned i=j+1; i<choose; i++){
_temp.push_back(sub[x][i]);
}
sub.push_back(_temp);
}
}
}
cout<<sub.size()<<endl;
for(unsigned i=0; i<sub.size(); i++){
vec_out(sub[i]);
}
return 0;
}
inline void vec_in(vector<unsigned>& vec, unsigned& size){
for(unsigned i=0; i<size; i++){
unsigned k;
cin>>k;
vec.push_back(k);
}
}
inline void vec_out(vector<unsigned>& vec){
for(unsigned i=0; i<vec.size(); i++){
cout<<vec[i]<<" ";
}
cout<<endl;
}
inline void vec_sub(vector<vector<unsigned>>& sub, vector<unsigned>& vec,
unsigned& size){
for(unsigned i=0; i<vec.size(); i++){
//if(i+size==vec.size()){break;}
vector<unsigned> temp;
unsigned x=i;
for(unsigned k=0; k<size; k++){
temp.push_back(vec[x]);
x++;
if(x==vec.size()){x=0;}
}
sub.push_back(temp);
}
}
This will not print in reverse order like you have done in you example. Print by reversing the arrays once and you will get your answer completely!
The idea behind this is :
1. Say you have 5 numbers : 1 2 3 4 5 and you want to choose 3 at a time then
2. Find the sub-arrays in serial order :
1 2 3
2 3 4
3 4 5
4 5 1
5 1 2
3. These will be first n sub-arrays of an array of length n
4. Now, take 1 from 1st sub-array and 3,4 from 2nd sub-array and make another sub-array from these 3 elements, then take 4,5 from 3rd sub-array and do the same. Do not take elements from last two sub arrays as after that the elements will start repeating.
5. Now take 1,2 from first sub-array and take 4 from 2nd sub-arr make one sub-array and take 5 from 3rd sub-arr and make one array
6. Push all these arrays back to the list of arrays you are having.
7. Do the same pattern from the 2nd sub-array but don't take elements from where the fist element of your array starts matching the last element that you will throw back from a sub-array below the array you are working on [ In the previous case the working sub-arr was 1st one and we didn't start taking elements from 4th sub array! ]
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54970636%2fhow-can-i-make-an-algorithm-in-c-for-finding-variations-of-a-set-without-repet%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
This code generates arrangements of k items from n in lexicographic order, packed into integer for simplicity (so 153 corresponds to (1,5,3))
void GenArrangement(int n, int k, int idx, int used, int arran) {
if (idx == k) {
std::cout << arran << std::endl;
return;
}
for (int i = 0; i < n; i++)
if (0 == (used & (1 << i)))
GenArrangement(n, k, idx + 1, used | (1 << i), arran * 10 + (i + 1));
}
int main()
{
GenArrangement(5, 3, 0, 0, 0);
}
123
124
125
132
134
135
142
143
145
152
153
154
213
214
215
231
234
235
241
243
245
251
253
254
312
314
315
321
324
325
341
342
345
351
352
354
412
413
415
421
423
425
431
432
435
451
452
453
512
513
514
521
523
524
531
532
534
541
542
543
add a comment |
This code generates arrangements of k items from n in lexicographic order, packed into integer for simplicity (so 153 corresponds to (1,5,3))
void GenArrangement(int n, int k, int idx, int used, int arran) {
if (idx == k) {
std::cout << arran << std::endl;
return;
}
for (int i = 0; i < n; i++)
if (0 == (used & (1 << i)))
GenArrangement(n, k, idx + 1, used | (1 << i), arran * 10 + (i + 1));
}
int main()
{
GenArrangement(5, 3, 0, 0, 0);
}
123
124
125
132
134
135
142
143
145
152
153
154
213
214
215
231
234
235
241
243
245
251
253
254
312
314
315
321
324
325
341
342
345
351
352
354
412
413
415
421
423
425
431
432
435
451
452
453
512
513
514
521
523
524
531
532
534
541
542
543
add a comment |
This code generates arrangements of k items from n in lexicographic order, packed into integer for simplicity (so 153 corresponds to (1,5,3))
void GenArrangement(int n, int k, int idx, int used, int arran) {
if (idx == k) {
std::cout << arran << std::endl;
return;
}
for (int i = 0; i < n; i++)
if (0 == (used & (1 << i)))
GenArrangement(n, k, idx + 1, used | (1 << i), arran * 10 + (i + 1));
}
int main()
{
GenArrangement(5, 3, 0, 0, 0);
}
123
124
125
132
134
135
142
143
145
152
153
154
213
214
215
231
234
235
241
243
245
251
253
254
312
314
315
321
324
325
341
342
345
351
352
354
412
413
415
421
423
425
431
432
435
451
452
453
512
513
514
521
523
524
531
532
534
541
542
543
This code generates arrangements of k items from n in lexicographic order, packed into integer for simplicity (so 153 corresponds to (1,5,3))
void GenArrangement(int n, int k, int idx, int used, int arran) {
if (idx == k) {
std::cout << arran << std::endl;
return;
}
for (int i = 0; i < n; i++)
if (0 == (used & (1 << i)))
GenArrangement(n, k, idx + 1, used | (1 << i), arran * 10 + (i + 1));
}
int main()
{
GenArrangement(5, 3, 0, 0, 0);
}
123
124
125
132
134
135
142
143
145
152
153
154
213
214
215
231
234
235
241
243
245
251
253
254
312
314
315
321
324
325
341
342
345
351
352
354
412
413
415
421
423
425
431
432
435
451
452
453
512
513
514
521
523
524
531
532
534
541
542
543
answered 11 hours ago
MBoMBo
49k23050
49k23050
add a comment |
add a comment |
You can iterate over every subset with a bitmask.
for(unsigned int i = 0; i < (1<<10);i++)
When you do not need portable code you could use
__builtin_popcount(int)
To get the number of 1s in the binary representation at least in gcc with an x86 processor.
for(unsigned int i = 0; i < (1<<10);i++) {
if(__builtin_popcount(i) == 4) { //Check if this subset contains exactly 4 elements
std::string s;
for(int j = 0; j < 10; j++) {
if(i&(1<<j)) { //Check if the bit on the j`th is a one
s.push_back(to_string(j));
}
}
v.push_back(s);
}
}
I am aware of this, but this prints combinations, rather than variations, which is not what I need.
– Pero
11 hours ago
no need to use popcnt, you can use normal slower way of counting en.wikichip.org/wiki/population_count
– NoSenseEtAl
11 hours ago
@Pero when you have the combinations, you can use next permutation on these (which are much smaller)
– Unlikus
11 hours ago
add a comment |
You can iterate over every subset with a bitmask.
for(unsigned int i = 0; i < (1<<10);i++)
When you do not need portable code you could use
__builtin_popcount(int)
To get the number of 1s in the binary representation at least in gcc with an x86 processor.
for(unsigned int i = 0; i < (1<<10);i++) {
if(__builtin_popcount(i) == 4) { //Check if this subset contains exactly 4 elements
std::string s;
for(int j = 0; j < 10; j++) {
if(i&(1<<j)) { //Check if the bit on the j`th is a one
s.push_back(to_string(j));
}
}
v.push_back(s);
}
}
I am aware of this, but this prints combinations, rather than variations, which is not what I need.
– Pero
11 hours ago
no need to use popcnt, you can use normal slower way of counting en.wikichip.org/wiki/population_count
– NoSenseEtAl
11 hours ago
@Pero when you have the combinations, you can use next permutation on these (which are much smaller)
– Unlikus
11 hours ago
add a comment |
You can iterate over every subset with a bitmask.
for(unsigned int i = 0; i < (1<<10);i++)
When you do not need portable code you could use
__builtin_popcount(int)
To get the number of 1s in the binary representation at least in gcc with an x86 processor.
for(unsigned int i = 0; i < (1<<10);i++) {
if(__builtin_popcount(i) == 4) { //Check if this subset contains exactly 4 elements
std::string s;
for(int j = 0; j < 10; j++) {
if(i&(1<<j)) { //Check if the bit on the j`th is a one
s.push_back(to_string(j));
}
}
v.push_back(s);
}
}
You can iterate over every subset with a bitmask.
for(unsigned int i = 0; i < (1<<10);i++)
When you do not need portable code you could use
__builtin_popcount(int)
To get the number of 1s in the binary representation at least in gcc with an x86 processor.
for(unsigned int i = 0; i < (1<<10);i++) {
if(__builtin_popcount(i) == 4) { //Check if this subset contains exactly 4 elements
std::string s;
for(int j = 0; j < 10; j++) {
if(i&(1<<j)) { //Check if the bit on the j`th is a one
s.push_back(to_string(j));
}
}
v.push_back(s);
}
}
answered 11 hours ago
UnlikusUnlikus
876
876
I am aware of this, but this prints combinations, rather than variations, which is not what I need.
– Pero
11 hours ago
no need to use popcnt, you can use normal slower way of counting en.wikichip.org/wiki/population_count
– NoSenseEtAl
11 hours ago
@Pero when you have the combinations, you can use next permutation on these (which are much smaller)
– Unlikus
11 hours ago
add a comment |
I am aware of this, but this prints combinations, rather than variations, which is not what I need.
– Pero
11 hours ago
no need to use popcnt, you can use normal slower way of counting en.wikichip.org/wiki/population_count
– NoSenseEtAl
11 hours ago
@Pero when you have the combinations, you can use next permutation on these (which are much smaller)
– Unlikus
11 hours ago
I am aware of this, but this prints combinations, rather than variations, which is not what I need.
– Pero
11 hours ago
I am aware of this, but this prints combinations, rather than variations, which is not what I need.
– Pero
11 hours ago
no need to use popcnt, you can use normal slower way of counting en.wikichip.org/wiki/population_count
– NoSenseEtAl
11 hours ago
no need to use popcnt, you can use normal slower way of counting en.wikichip.org/wiki/population_count
– NoSenseEtAl
11 hours ago
@Pero when you have the combinations, you can use next permutation on these (which are much smaller)
– Unlikus
11 hours ago
@Pero when you have the combinations, you can use next permutation on these (which are much smaller)
– Unlikus
11 hours ago
add a comment |
The slowness is due to generating all n! permutations, even when only a fraction of them is required. Your complexity is around O(n! * k log n), where O(k log n) is an upper bound on the complexity to query the std::map
with all of the permutations.
The answer by MBo is limited to 9 values (1..9). Even if it is extended to printing longer values, they are still limited by number of bits (usually 31 for int, and 64 bit if uint64_t is available).
Here it is:
void print_permutations_impl(std::ostream & out, std::vector<int> & values,
unsigned k, std::vector<int> & permutation_stack)
{
if (k == permutation_stack.size())
{
const char* prefix = "";
for (auto elem: permutation_stack) {
out << prefix << elem;
prefix = ", ";
}
out << 'n';
return;
}
auto end_valid = values.size() - permutation_stack.size();
permutation_stack.push_back(0);
for (unsigned i=0 ; i < end_valid; ++i) {
permutation_stack.back() = values[i];
std::swap(values[i], values[end_valid - 1]);
print_permutations_impl(out, values, k, permutation_stack);
std::swap(values[i], values[end_valid - 1]);
}
permutation_stack.pop_back();
}
void print_permutations(std::ostream & out, const std::vector<int> & values, int k)
{
std::vector<int> unique = values;
std::sort(unique.begin(), unique.end());
unique.erase(std::unique(unique.begin(), unique.end()),
unique.end());
std::vector<int> current_permutation;
print_permutations_impl(out, unique, k, current_permutation);
}
It works in sub-second speed for N=100 and K=2.
add a comment |
The slowness is due to generating all n! permutations, even when only a fraction of them is required. Your complexity is around O(n! * k log n), where O(k log n) is an upper bound on the complexity to query the std::map
with all of the permutations.
The answer by MBo is limited to 9 values (1..9). Even if it is extended to printing longer values, they are still limited by number of bits (usually 31 for int, and 64 bit if uint64_t is available).
Here it is:
void print_permutations_impl(std::ostream & out, std::vector<int> & values,
unsigned k, std::vector<int> & permutation_stack)
{
if (k == permutation_stack.size())
{
const char* prefix = "";
for (auto elem: permutation_stack) {
out << prefix << elem;
prefix = ", ";
}
out << 'n';
return;
}
auto end_valid = values.size() - permutation_stack.size();
permutation_stack.push_back(0);
for (unsigned i=0 ; i < end_valid; ++i) {
permutation_stack.back() = values[i];
std::swap(values[i], values[end_valid - 1]);
print_permutations_impl(out, values, k, permutation_stack);
std::swap(values[i], values[end_valid - 1]);
}
permutation_stack.pop_back();
}
void print_permutations(std::ostream & out, const std::vector<int> & values, int k)
{
std::vector<int> unique = values;
std::sort(unique.begin(), unique.end());
unique.erase(std::unique(unique.begin(), unique.end()),
unique.end());
std::vector<int> current_permutation;
print_permutations_impl(out, unique, k, current_permutation);
}
It works in sub-second speed for N=100 and K=2.
add a comment |
The slowness is due to generating all n! permutations, even when only a fraction of them is required. Your complexity is around O(n! * k log n), where O(k log n) is an upper bound on the complexity to query the std::map
with all of the permutations.
The answer by MBo is limited to 9 values (1..9). Even if it is extended to printing longer values, they are still limited by number of bits (usually 31 for int, and 64 bit if uint64_t is available).
Here it is:
void print_permutations_impl(std::ostream & out, std::vector<int> & values,
unsigned k, std::vector<int> & permutation_stack)
{
if (k == permutation_stack.size())
{
const char* prefix = "";
for (auto elem: permutation_stack) {
out << prefix << elem;
prefix = ", ";
}
out << 'n';
return;
}
auto end_valid = values.size() - permutation_stack.size();
permutation_stack.push_back(0);
for (unsigned i=0 ; i < end_valid; ++i) {
permutation_stack.back() = values[i];
std::swap(values[i], values[end_valid - 1]);
print_permutations_impl(out, values, k, permutation_stack);
std::swap(values[i], values[end_valid - 1]);
}
permutation_stack.pop_back();
}
void print_permutations(std::ostream & out, const std::vector<int> & values, int k)
{
std::vector<int> unique = values;
std::sort(unique.begin(), unique.end());
unique.erase(std::unique(unique.begin(), unique.end()),
unique.end());
std::vector<int> current_permutation;
print_permutations_impl(out, unique, k, current_permutation);
}
It works in sub-second speed for N=100 and K=2.
The slowness is due to generating all n! permutations, even when only a fraction of them is required. Your complexity is around O(n! * k log n), where O(k log n) is an upper bound on the complexity to query the std::map
with all of the permutations.
The answer by MBo is limited to 9 values (1..9). Even if it is extended to printing longer values, they are still limited by number of bits (usually 31 for int, and 64 bit if uint64_t is available).
Here it is:
void print_permutations_impl(std::ostream & out, std::vector<int> & values,
unsigned k, std::vector<int> & permutation_stack)
{
if (k == permutation_stack.size())
{
const char* prefix = "";
for (auto elem: permutation_stack) {
out << prefix << elem;
prefix = ", ";
}
out << 'n';
return;
}
auto end_valid = values.size() - permutation_stack.size();
permutation_stack.push_back(0);
for (unsigned i=0 ; i < end_valid; ++i) {
permutation_stack.back() = values[i];
std::swap(values[i], values[end_valid - 1]);
print_permutations_impl(out, values, k, permutation_stack);
std::swap(values[i], values[end_valid - 1]);
}
permutation_stack.pop_back();
}
void print_permutations(std::ostream & out, const std::vector<int> & values, int k)
{
std::vector<int> unique = values;
std::sort(unique.begin(), unique.end());
unique.erase(std::unique(unique.begin(), unique.end()),
unique.end());
std::vector<int> current_permutation;
print_permutations_impl(out, unique, k, current_permutation);
}
It works in sub-second speed for N=100 and K=2.
edited 7 hours ago
answered 7 hours ago
Michael VekslerMichael Veksler
3,4121517
3,4121517
add a comment |
add a comment |
//finds permutations of an array
#include<iostream>
#include<vector>
using namespace std;
inline void vec_in(vector<unsigned>&, unsigned&);
inline void vec_out(vector<unsigned>&);
inline void vec_sub(vector<vector<unsigned>>&, vector<unsigned>&, unsigned&);
int main(){
unsigned size;
cout<<"SIZE : ";
cin>>size;
vector<unsigned> vec;
vec_in(vec,size);
unsigned choose;
cout<<"CHOOSE : ";
cin>>choose;
vector<vector<unsigned>> sub;
vec_sub(sub, vec, choose);
size=sub.size();
for(unsigned y=0; y<size-2; y++){
for(unsigned j=0; j<choose-1; j++){
vector<unsigned> temp;
for(unsigned i=0; i<=j; i++){
temp.push_back(sub[y][i]);
}
for(unsigned x=y+1; x<size; x++){
if(temp[0]==sub[x][choose-1]){break;}
vector<unsigned> _temp;
_temp=temp;
for(unsigned i=j+1; i<choose; i++){
_temp.push_back(sub[x][i]);
}
sub.push_back(_temp);
}
}
}
cout<<sub.size()<<endl;
for(unsigned i=0; i<sub.size(); i++){
vec_out(sub[i]);
}
return 0;
}
inline void vec_in(vector<unsigned>& vec, unsigned& size){
for(unsigned i=0; i<size; i++){
unsigned k;
cin>>k;
vec.push_back(k);
}
}
inline void vec_out(vector<unsigned>& vec){
for(unsigned i=0; i<vec.size(); i++){
cout<<vec[i]<<" ";
}
cout<<endl;
}
inline void vec_sub(vector<vector<unsigned>>& sub, vector<unsigned>& vec,
unsigned& size){
for(unsigned i=0; i<vec.size(); i++){
//if(i+size==vec.size()){break;}
vector<unsigned> temp;
unsigned x=i;
for(unsigned k=0; k<size; k++){
temp.push_back(vec[x]);
x++;
if(x==vec.size()){x=0;}
}
sub.push_back(temp);
}
}
This will not print in reverse order like you have done in you example. Print by reversing the arrays once and you will get your answer completely!
The idea behind this is :
1. Say you have 5 numbers : 1 2 3 4 5 and you want to choose 3 at a time then
2. Find the sub-arrays in serial order :
1 2 3
2 3 4
3 4 5
4 5 1
5 1 2
3. These will be first n sub-arrays of an array of length n
4. Now, take 1 from 1st sub-array and 3,4 from 2nd sub-array and make another sub-array from these 3 elements, then take 4,5 from 3rd sub-array and do the same. Do not take elements from last two sub arrays as after that the elements will start repeating.
5. Now take 1,2 from first sub-array and take 4 from 2nd sub-arr make one sub-array and take 5 from 3rd sub-arr and make one array
6. Push all these arrays back to the list of arrays you are having.
7. Do the same pattern from the 2nd sub-array but don't take elements from where the fist element of your array starts matching the last element that you will throw back from a sub-array below the array you are working on [ In the previous case the working sub-arr was 1st one and we didn't start taking elements from 4th sub array! ]
add a comment |
//finds permutations of an array
#include<iostream>
#include<vector>
using namespace std;
inline void vec_in(vector<unsigned>&, unsigned&);
inline void vec_out(vector<unsigned>&);
inline void vec_sub(vector<vector<unsigned>>&, vector<unsigned>&, unsigned&);
int main(){
unsigned size;
cout<<"SIZE : ";
cin>>size;
vector<unsigned> vec;
vec_in(vec,size);
unsigned choose;
cout<<"CHOOSE : ";
cin>>choose;
vector<vector<unsigned>> sub;
vec_sub(sub, vec, choose);
size=sub.size();
for(unsigned y=0; y<size-2; y++){
for(unsigned j=0; j<choose-1; j++){
vector<unsigned> temp;
for(unsigned i=0; i<=j; i++){
temp.push_back(sub[y][i]);
}
for(unsigned x=y+1; x<size; x++){
if(temp[0]==sub[x][choose-1]){break;}
vector<unsigned> _temp;
_temp=temp;
for(unsigned i=j+1; i<choose; i++){
_temp.push_back(sub[x][i]);
}
sub.push_back(_temp);
}
}
}
cout<<sub.size()<<endl;
for(unsigned i=0; i<sub.size(); i++){
vec_out(sub[i]);
}
return 0;
}
inline void vec_in(vector<unsigned>& vec, unsigned& size){
for(unsigned i=0; i<size; i++){
unsigned k;
cin>>k;
vec.push_back(k);
}
}
inline void vec_out(vector<unsigned>& vec){
for(unsigned i=0; i<vec.size(); i++){
cout<<vec[i]<<" ";
}
cout<<endl;
}
inline void vec_sub(vector<vector<unsigned>>& sub, vector<unsigned>& vec,
unsigned& size){
for(unsigned i=0; i<vec.size(); i++){
//if(i+size==vec.size()){break;}
vector<unsigned> temp;
unsigned x=i;
for(unsigned k=0; k<size; k++){
temp.push_back(vec[x]);
x++;
if(x==vec.size()){x=0;}
}
sub.push_back(temp);
}
}
This will not print in reverse order like you have done in you example. Print by reversing the arrays once and you will get your answer completely!
The idea behind this is :
1. Say you have 5 numbers : 1 2 3 4 5 and you want to choose 3 at a time then
2. Find the sub-arrays in serial order :
1 2 3
2 3 4
3 4 5
4 5 1
5 1 2
3. These will be first n sub-arrays of an array of length n
4. Now, take 1 from 1st sub-array and 3,4 from 2nd sub-array and make another sub-array from these 3 elements, then take 4,5 from 3rd sub-array and do the same. Do not take elements from last two sub arrays as after that the elements will start repeating.
5. Now take 1,2 from first sub-array and take 4 from 2nd sub-arr make one sub-array and take 5 from 3rd sub-arr and make one array
6. Push all these arrays back to the list of arrays you are having.
7. Do the same pattern from the 2nd sub-array but don't take elements from where the fist element of your array starts matching the last element that you will throw back from a sub-array below the array you are working on [ In the previous case the working sub-arr was 1st one and we didn't start taking elements from 4th sub array! ]
add a comment |
//finds permutations of an array
#include<iostream>
#include<vector>
using namespace std;
inline void vec_in(vector<unsigned>&, unsigned&);
inline void vec_out(vector<unsigned>&);
inline void vec_sub(vector<vector<unsigned>>&, vector<unsigned>&, unsigned&);
int main(){
unsigned size;
cout<<"SIZE : ";
cin>>size;
vector<unsigned> vec;
vec_in(vec,size);
unsigned choose;
cout<<"CHOOSE : ";
cin>>choose;
vector<vector<unsigned>> sub;
vec_sub(sub, vec, choose);
size=sub.size();
for(unsigned y=0; y<size-2; y++){
for(unsigned j=0; j<choose-1; j++){
vector<unsigned> temp;
for(unsigned i=0; i<=j; i++){
temp.push_back(sub[y][i]);
}
for(unsigned x=y+1; x<size; x++){
if(temp[0]==sub[x][choose-1]){break;}
vector<unsigned> _temp;
_temp=temp;
for(unsigned i=j+1; i<choose; i++){
_temp.push_back(sub[x][i]);
}
sub.push_back(_temp);
}
}
}
cout<<sub.size()<<endl;
for(unsigned i=0; i<sub.size(); i++){
vec_out(sub[i]);
}
return 0;
}
inline void vec_in(vector<unsigned>& vec, unsigned& size){
for(unsigned i=0; i<size; i++){
unsigned k;
cin>>k;
vec.push_back(k);
}
}
inline void vec_out(vector<unsigned>& vec){
for(unsigned i=0; i<vec.size(); i++){
cout<<vec[i]<<" ";
}
cout<<endl;
}
inline void vec_sub(vector<vector<unsigned>>& sub, vector<unsigned>& vec,
unsigned& size){
for(unsigned i=0; i<vec.size(); i++){
//if(i+size==vec.size()){break;}
vector<unsigned> temp;
unsigned x=i;
for(unsigned k=0; k<size; k++){
temp.push_back(vec[x]);
x++;
if(x==vec.size()){x=0;}
}
sub.push_back(temp);
}
}
This will not print in reverse order like you have done in you example. Print by reversing the arrays once and you will get your answer completely!
The idea behind this is :
1. Say you have 5 numbers : 1 2 3 4 5 and you want to choose 3 at a time then
2. Find the sub-arrays in serial order :
1 2 3
2 3 4
3 4 5
4 5 1
5 1 2
3. These will be first n sub-arrays of an array of length n
4. Now, take 1 from 1st sub-array and 3,4 from 2nd sub-array and make another sub-array from these 3 elements, then take 4,5 from 3rd sub-array and do the same. Do not take elements from last two sub arrays as after that the elements will start repeating.
5. Now take 1,2 from first sub-array and take 4 from 2nd sub-arr make one sub-array and take 5 from 3rd sub-arr and make one array
6. Push all these arrays back to the list of arrays you are having.
7. Do the same pattern from the 2nd sub-array but don't take elements from where the fist element of your array starts matching the last element that you will throw back from a sub-array below the array you are working on [ In the previous case the working sub-arr was 1st one and we didn't start taking elements from 4th sub array! ]
//finds permutations of an array
#include<iostream>
#include<vector>
using namespace std;
inline void vec_in(vector<unsigned>&, unsigned&);
inline void vec_out(vector<unsigned>&);
inline void vec_sub(vector<vector<unsigned>>&, vector<unsigned>&, unsigned&);
int main(){
unsigned size;
cout<<"SIZE : ";
cin>>size;
vector<unsigned> vec;
vec_in(vec,size);
unsigned choose;
cout<<"CHOOSE : ";
cin>>choose;
vector<vector<unsigned>> sub;
vec_sub(sub, vec, choose);
size=sub.size();
for(unsigned y=0; y<size-2; y++){
for(unsigned j=0; j<choose-1; j++){
vector<unsigned> temp;
for(unsigned i=0; i<=j; i++){
temp.push_back(sub[y][i]);
}
for(unsigned x=y+1; x<size; x++){
if(temp[0]==sub[x][choose-1]){break;}
vector<unsigned> _temp;
_temp=temp;
for(unsigned i=j+1; i<choose; i++){
_temp.push_back(sub[x][i]);
}
sub.push_back(_temp);
}
}
}
cout<<sub.size()<<endl;
for(unsigned i=0; i<sub.size(); i++){
vec_out(sub[i]);
}
return 0;
}
inline void vec_in(vector<unsigned>& vec, unsigned& size){
for(unsigned i=0; i<size; i++){
unsigned k;
cin>>k;
vec.push_back(k);
}
}
inline void vec_out(vector<unsigned>& vec){
for(unsigned i=0; i<vec.size(); i++){
cout<<vec[i]<<" ";
}
cout<<endl;
}
inline void vec_sub(vector<vector<unsigned>>& sub, vector<unsigned>& vec,
unsigned& size){
for(unsigned i=0; i<vec.size(); i++){
//if(i+size==vec.size()){break;}
vector<unsigned> temp;
unsigned x=i;
for(unsigned k=0; k<size; k++){
temp.push_back(vec[x]);
x++;
if(x==vec.size()){x=0;}
}
sub.push_back(temp);
}
}
This will not print in reverse order like you have done in you example. Print by reversing the arrays once and you will get your answer completely!
The idea behind this is :
1. Say you have 5 numbers : 1 2 3 4 5 and you want to choose 3 at a time then
2. Find the sub-arrays in serial order :
1 2 3
2 3 4
3 4 5
4 5 1
5 1 2
3. These will be first n sub-arrays of an array of length n
4. Now, take 1 from 1st sub-array and 3,4 from 2nd sub-array and make another sub-array from these 3 elements, then take 4,5 from 3rd sub-array and do the same. Do not take elements from last two sub arrays as after that the elements will start repeating.
5. Now take 1,2 from first sub-array and take 4 from 2nd sub-arr make one sub-array and take 5 from 3rd sub-arr and make one array
6. Push all these arrays back to the list of arrays you are having.
7. Do the same pattern from the 2nd sub-array but don't take elements from where the fist element of your array starts matching the last element that you will throw back from a sub-array below the array you are working on [ In the previous case the working sub-arr was 1st one and we didn't start taking elements from 4th sub array! ]
edited 8 hours ago
answered 8 hours ago
brightprogrammerbrightprogrammer
308
308
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54970636%2fhow-can-i-make-an-algorithm-in-c-for-finding-variations-of-a-set-without-repet%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
You might use
next_permutation
on abitset
(of size n, with k true). bitset shows valid item from thevector
.– Jarod42
12 hours ago
@Jarod42 how do I use
next_permutation
onbitset
? I can't find how to.– Pero
11 hours ago