bad_alloc() when recursively producing combinations and storing to vector - c++

Overview:
I am trying to produce combinations from a set of characters, with a specific starting character, where each combination is of a certain length within a range. For example if my set of characters is {A,B,C,D} and starting prefix 'A' then my combinations for lengths 1 through 3 are: A, AA, AB, AC, AD, AAA, AAB, AAC, AAD,....,ADD.
Problem: I produce each combination recursively. The problem is when I try to store combinations to a vector for a larger set of characters for range of lengths 1 through 8 (which I obviously understand are many combinations) I get a bad_alloc core dumped error. My understanding is that this means I ran out of memory (possibly due to my vector being full). I want to try allocating this vector to the heap and keeping it global. Below is my current code before attempting to modify:
#include <iostream>
#include <vector>
#include <string>
#include <time.h>
using namespace std;
#define SIZE_SET 15 // sizeof set below, set of characters to create permutations from
char set[] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O'};
void ProducePerms(vector<string>&, string, const int, const int);
int main(){
// Timing program run time
clock_t t1, t2;
t1 = clock();
cout << "Starting time" << endl;
vector<string> perms; // Stores permutations
string start_prefix = "B"; // All permutations of lengths 1-8 begin with this prefix
int length = 8; // Maximum length of permutation
// Produce lengths 1-8 permutations starting with prefix
for(int l = 0; l < length; l++){
ProducePerms(perms, start_prefix, SIZE_SET, l);
}
// End run time
t2 = clock();
cout << "\nTime elapsed: " << (t2-t1)/(double)CLOCKS_PER_SEC << endl << endl;
return 0;
}
void ProducePerms(vector<string>& vec, string prefix, const int n, const int length){
if(length == 0){
vec.push_back(prefix);
}
else{
if(length == 1){
for(int j = 0; j < n; j++){
vec.push_back(prefix + set[j]);
}
}
else{
for(int i = 0; i < n; i++){
ProducePerms(vec, prefix + set[i], n, length - 1);
}
}
}
}
Also if anyone has any suggestions on how I can adapt this to using pthreads that would be helpful. I am currently thinking of creating pthreads to compute combinations for a certain length.

Related

C++: How to Generate All Combinations of a Vector of Digits of Length N, disregarding order?

So I need to combine a specific number (not string) of digits from a vector of possible ones (all 0-9, not characters) in an N-digit number (not binary, then). However, I cannot have any extra permutations appear: for example 1234, 4321, 3124... are now the same and cannot be all outputed. Only one can be. This is hard because other questions cover these permutions by using std::next_permutation, but I still need the different combinations. My attempts at trying to remove permutations have failed, so how do you do this? Here is my current code with comments:
#include <iostream>
#include <vector>
using namespace std;
#define ll long long
int n = 0, m = 0, temp; //n is number of available digits
//m is the length of the desired numbers
//temp is used to cin
vector <int> given;
//vector of digits that can be used
vector <int> num;
//the vector to contain a created valid number
void generate(vector <int> vec, int m) {
//recursive function to generate all numbers
if (m == 0) {
for (int x : num) {
cout << x;
}
cout << '\n';
return;
}
for (int i = 0; i < given.size(); i++) {
num.push_back(given[i]); //add digit to number
int save = given[i];
given.erase(given.begin() + i);
//no repeating digits, save the used one and delete
//however, permutations can still pass, which is undesirable
generate(vec, m - 1);
//recursive
num.pop_back();
//undo move
given.insert(given.begin() + i, save);
//redo insert deleted digit
}
}
int main () {
cin >> n;
//input number of available digits
for (int i = 0; i < n; i++) {
cin >> temp;
given.push_back(temp); //input digits
}
cin >> m;
//input length of valid numbers
generate(given, m); //start recursive generation function
return 0;
}
I tried deleting permutations before printing them and erasing more digits to stop generating permutations, but they all failed. Lots of other questions still used std::next_permutation, which was not helpful.
Unlike some people who suggested binary strings in some comments, you can begin by having a recursive function that can go two ways as an on/off switch to decide whether or not to include a given digit. I personally like using a recursive function to do this and a check for length at the end to actually print the number of the desired len, demonstrated in the code below:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int givencount = 0, temp = 0, len = 0;
vector <int> given;
string creatednum;
void generate(int m) {
if (m == givencount) {
if (creatednum.length() == len) {
cout << creatednum << '\n';
}
return;
}
for (int i = 0; i < 2; i++) {
if (i == 1) {
generate(m + 1);
continue;
}
creatednum = creatednum + ((char) ('0' + given[m]));
generate(m + 1);
creatednum.erase(creatednum.begin() + creatednum.length() - 1);
}
}
int main () {
cin >> givencount;
for (int i = 0; i < givencount; i++) {
cin >> temp;
given.push_back(temp);
}
cin >> len;
generate(0);
return 0;
}

Minimum number of steps to equalize distinct character of the string [duplicate]

This question already has answers here:
How to find the minimum number of operation(s) to make the string balanced?
(5 answers)
Closed 1 year ago.
I'm trying to write this program that asks for user input of string, my job is to print out the minimum number of steps required to equalize the frequency of distinct characters of the string.
Example
Input
6
aba
abba
abbc
abbbc
codedigger
codealittle
Output
1
0
1
2
2
3
Here is my program:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <unordered_map>
using namespace std;
int main()
{
unordered_map<char, int >m;
vector<int> vec1, vec2;
string s;
int n;
cin >> n;
cin.ignore();
for (int i = 0; i < n; ++i)
{
m.clear();
vec1.clear();
getline(cin, s);
for (int i = 0; i < s.size(); i++)
m[s[i]]++;
for (auto itr : m)
vec1.push_back(itr.second);
sort(vec1.begin(), vec1.end());
int mid = vec1[vec1.size() / 2];
int ans = 0;
for (auto itr : vec1)
ans += abs(mid - itr);
vec2.push_back(ans);
}
for (int i = 0; i < vec2.size(); ++i)
cout << vec2[i] << endl;
}
What I tried to do is for each test case:
Using an unordered_map to count the frequency of the characters of the string.
Push the key values of the map to a vector.
Sort the vector in ascending order.
Calculate the middle element of the vector to equalize the distinct characters with as least steps as possible.
The result will add the difference between the middle element with the current element.
Push the result to another vector and print it.
But my result is wrong at test case number 5:
1
0
1
2
3 // The actual result is 2
3
I don't understand why I get the wrong result, can anyone help me with this? Thanks for your help!
The issue is that your algorithm is not finding the optimal number of steps.
Consider the string you obtained an incorrect answer for: codedigger. It has 4 letters of frequency 1 (coir) and 3 letters of frequency 2 (ddeegg).
The optimal way is not to convert half the letters of frequency 2 into some new character (not present in the string) to make all frequency 1. From my understanding, your implementation is counting the number of steps that this would require.
Instead, consider this:
c[o]dedigge[r]
If I replace o with c and r with i, I obtain:
ccdediggei
which already has equalized character frequencies. You will note that I only performed 2 edits.
So without giving you a solution, I believe this might still answer your question? Perhaps with this in mind, you can come up with a different algorithm that is able to find the optimal number of edits.
Your code correctly measures the frequencies of each letter, as the important information.
But then, there were mainly two issues:
The main target value (final equalized frequency) is not necessarily equal to the median value. In particular, this value must divide the total number of letters
For a given targeted height value, your calculation of the number of steps is not correct. You must pay attention not to count twice the same mutation. Moreover, the general formula is different, depending the final number of different letters is equal, less or higher than the original number of letters.
The following code focuses on correctness, not on efficiency too much. It considers all the possible values of the targeted height (frequency), i.e. all the divisors of the total number of letters.
If efficiency is really a concern (not mentioned in the post), then for example one could consider that the best value is unlikely to be very far from the initial average frequency value.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include <unordered_map>
// calculates the number of steps for a given target
// This code assumes that the frequencies are sorted in descending order.
int n_steps (std::vector<int>& freq, int target, int nchar) {
int sum = 0;
int n = freq.size();
int m = nchar/target; // new number of characters
int imax = std::min (n, m);
for (int i = 0; i < imax; ++i) {
sum += std::abs (freq[i] - target);
}
for (int i = imax; i < n; ++i) {
sum += freq[i];
}
if (m > n) sum += m-n;
sum /= 2;
return sum;
}
int main() {
std::unordered_map<char, int >m;
std::vector<int> vec1, vec2;
std::string s;
int n;
std::cin >> n;
std::cin.ignore();
for (int i = 0; i < n; ++i)
{
m.clear();
vec1.clear();
//getline(cin, s);
std::cin >> s;
for (int i = 0; i < s.size(); i++)
m[s[i]]++;
for (auto itr : m)
vec1.push_back(itr.second);
sort(vec1.begin(), vec1.end(), std::greater<int>());
int nchar = s.size();
int n_min_oper = nchar+1;
for (int target = 1; target <= nchar; ++target) {
if (nchar % target) continue;
int n_oper = n_steps (vec1, target, nchar);
if (n_oper < n_min_oper) n_min_oper = n_oper;
}
vec2.push_back(n_min_oper);
}
for (int i = 0; i < vec2.size(); ++i)
std::cout << vec2[i] << std::endl;
}

All permutations of length k from n characters with repetition in CPP

I would like to know if there is already an implementation in CPP to find all permutations of n characters of length k(1,2,3,4 etc) with repetitions. I hope there is but i could not find.
For example if string= (A,B,C,D) and i want find all permutations of string with repetitions of length k =2.
The output will be something like :
AA
AB
AC
AD
.
.
.
DD
total permutations of 16.
Simple recursive solution which will work for you for sure.
Let me first re-write your specification: Print all permutations with repetition of characters
Given a string of length n, print all permutation of the given string.
Repetition of characters is allowed
For a given string of size n, there will be n^k possible strings of length "length". The idea is to start from an empty output string (we call it prefix in following code). One by one add all characters to prefix. For every character added, print all possible strings with current prefix by recursively calling for "length" equals to "length"-1.
#include <string>
#include <iostream>
void print_str(const char*,std::string,const int, const int);
int main()
{
int lenght = 2;
char str[] = {'A', 'B', 'C', 'D'};
int n = sizeof str;
print_str(str, "", n, lenght); //Note: this function works on all cases and not just the case above
return 0;
}
// The main recursive method to print all possible strings of length "length"
void print_str(const char str[],std::string prefix,const int n, const int lenght)
{
if (lenght == 1)
{
for (int j = 0; j < n; j++)
std::cout << prefix + str[j] << std::endl;
}//Base case: lenght = 1, print the string "lenght" times + the remaining letter
else
{
// One by one add all characters from "str" and recursively call for "lenght" equals to "lenght"-1
for (int i = 0; i < n; i++)
// Next character of input added
print_str(str, prefix + str[i], n, lenght - 1);
// "lenght" is decreased, because we have added a new character
}
}
Here is the execution of the code above:
References:
http://www.geeksforgeeks.org/print-all-permutations-with-repetition-of-characters/
http://www.geeksforgeeks.org/print-all-combinations-of-given-length/
Update: this update is writen answring the following spec.
I need one more help!! as i am new to CPP programming. Suppose if
length = 3 how can i make it to get all permutations starting from
length = 1 to length = 3 together in an array. Means to get all the
permutations of length =1, length =2 and length = 3 together stored in
an array
#include <string>
#include <iostream>
#include <vector>
void print_str(const char*,std::string,const int, const int);
std::vector<std::string> permutations ; // the vector permutations which will hold all the permutations,
//if you want you can use it for later use or you can use the array below which is nothing than a copy of this vector.
int NumberOfPermutations = 0; // this variable holds the number of permutations
int main()
{
int lenght = 3;
char str[] = {'A', 'B', 'C', 'D'};
int n = sizeof str;
//here we loop through all the possible lenghts 1, 2 and 3
for (int k = 1; k <= lenght; k++)
{
print_str(str, "", n, k); //Note: this function works on all cases and not just the case above
}
std::string* permut_array = new std::string[NumberOfPermutations]; // the array that we will use to store the permutations in
std::copy(permutations.begin(), permutations.end(), permut_array); // here we copy the vector into the array
//if you want you can use your array to print the permutation as folow
for (int k = 0; k < NumberOfPermutations; k++)
{
std::cout << permut_array[k] << std::endl;
}
return 0;
}
// The main recursive method to print all possible strings of length "length"
void print_str(const char str[],std::string prefix,const int n, const int lenght)
{
if (lenght == 1)
{
for (int j = 0; j < n; j++)
{
// i commented this ligne so that if you want to use your array to print your permutations you will not get a screnn with permutations printed 2 times
//std::cout << prefix + str[j] << std::endl;
permutations.push_back(prefix + str[j]); // the vector that we will use to store the permutations in
}
}//Base case: lenght = 1, print the string "lenght" times + the remaining letter
else
{
// One by one add all characters from "str" and recursively call for "lenght" equals to "lenght"-1
for (int i = 0; i < n; i++)
// Next character of input added
print_str(str, prefix + str[i], n, lenght - 1);
// "lenght" is decreased, because we have added a new character
}
NumberOfPermutations = permutations.size();
}
you can use std::next_permutation() as πάντα ῥεῖ said, but since you want to define the length and the char with repetitions, you can do something easy to realize it, as:
std::string s = "aabbccdd";
std::set<std::string> string_set;
std::sort(s.begin(), s.end());
do {
string_set.insert(s.substr(0, 2));
} while(std::next_permutation(s.begin(), s.end()));
for(auto i = string_set.begin(); i != string_set.end(); ++i)
std::cout << *i << std::endl;
This just isn't a permutation, which probably explains why you can't find an answer.
What you are actually asking is how to print the numbers 0..k-1 in base n, using digits A,B,C,D. I'll rewrite your example with familiar digits 0,1,2,3 :
00
01
02
03
10
11
12
13
..
33
There's no standard C++ method for this, but now that you know what it's called there's plenty of code on the web. Or just write it yourself. Hint: the last digit of i has value i % n.
This solution works out for all standard container and also static arrays. I think this can be used also for classes and structures
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <list>
#include <iterator>
template<typename InputIt, typename T>
bool nextPermutationWithRepetition(InputIt begin, InputIt end, T from_value, T to_value) {
auto it = std::find_if_not(std::make_reverse_iterator(end),
std::make_reverse_iterator(begin),
[&to_value](auto current) { return to_value == current; });
if (it == std::make_reverse_iterator(begin))
return false;
auto bound_element_iterator = std::prev(it.base());
(*bound_element_iterator)++;
std::fill(std::next(bound_element_iterator), end, from_value);
return true;
}
int main() {
std::list<int> vec(3, 0);
do {
std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
} while (nextPermutationWithRepetition(vec.begin(), vec.end(), 0, 2));
return 0;
}

Extremely slow random string generator

I came up with the below code to generate 100001 random strings.the strings should be unique. However, the below code takes hours to do the job. Can someone let me know how i can optimize it and why is it so slow?
string getRandomString(int length) {
static string charset = "abcdefghijklmnopqrstuvwxyz";
string result;
result.resize(length);
for (int i = 0; i < length; i++) {
result[i] = charset[rand() % charset.length()];
}
return result;
}
void main(){
srand(time(NULL));
vector<string> storeUnigrams;
int numUnigram = 100001;
string temp = "";
int minLen = 3;
int maxLen = 26;
int range = maxLen - minLen + 1;
int i =0;
while(i < numUnigram){
int lenOfRanString = rand()%range + minLen;
temp = getRandomString(lenOfRanString);
bool doesithave = false;
for(int j =0 ; j < storeUnigrams.size() ; j++){
if(temp.compare(storeUnigrams[j]) == 0){
doesithave = true;
break;
}
if(temp.compare(storeUnigrams[j]) < 0){
break;
}
}
if(!doesithave){
storeUnigrams.push_back(temp);
sort(storeUnigrams.begin(),storeUnigrams.end());
i++;
}
}
There are two factors that make your code slow:
Checking by linear search whether the string already exists – O(n)
Sorting the vector in each iteration – O(n log n)
Use e.g. a set for storing the strings – it's sorted automatically, and checking for existence is fast:
int main(){
srand(time(NULL));
set<string> storeUnigrams;
int numUnigram = 100001;
int minLen = 3;
int maxLen = 26;
int range = maxLen - minLen + 1;
while(storeUnigrams.size() < numUnigram){
int lenOfRanString = rand()%range + minLen;
storeUnigrams.insert(getRandomString(lenOfRanString));
}
}
This code generates a unique random number only once and stores it in random_once[i].
The first for loop generates ad stores the random number.
The second for loop is used to get the pre-rendered random numbers stored in the random_once[i] array.
Yes generating 100001 random numbers will take hours if not days.
#include <ctime>
#include <iostream>
using namespace std;
int main()
{
int numUnigram = 3001;
int size=numUnigram;
int random_once[100001];
cout<<"Please wait: Generatng "<<numUnigram<<" random numbers ";
std::cout << '-' << std::flush;
srand(time(0));
for (int i=0;i<size;i++)
{
//This code generates a unique random number only once
//and stores it in random_once[i]
random_once[i]=rand() % size;
for(int j=0;j<i;j++) if (random_once[j]==random_once[i]) i--;
//loading animation
std::cout << "\b\\" << std::flush;
std::cout << "\b|" << std::flush;
std::cout << "\b/" << std::flush;
std::cout << "\b-" << std::flush;
}
cout<<" \n";
// this code dispays unique random numbers stored in random_once[i]
for ( i=0;i<size;i++) cout<<" "<<random_once[i]<<"\t";
cout<<" \n";
return 0;
}
Philipp answer is fine. Another approach would be to use a Self-balancing Binary Search Tree like Red Black Tree instead of Vector. You can perform search and insets in log(n) time. If search is empty, insert the element.
Define your variables outside the while loop - because they are getting redefined at each iteration
int lenOfRanString = rand()%range + minLen; ;
bool doesithave = false;
Update
Thought it's advised in many books, in practice with all the new compilers, this will not significantly improve the performance
Use char arrays instead of strings (the string class does a lot of stuff behind the scenes)

Are there any better methods to do permutation of string?

void permute(string elems, int mid, int end)
{
static int count;
if (mid == end) {
cout << ++count << " : " << elems << endl;
return ;
}
else {
for (int i = mid; i <= end; i++) {
swap(elems, mid, i);
permute(elems, mid + 1, end);
swap(elems, mid, i);
}
}
}
The above function shows the permutations of str(with str[0..mid-1] as a steady prefix, and str[mid..end] as a permutable suffix). So we can use permute(str, 0, str.size() - 1) to show all the permutations of one string.
But the function uses a recursive algorithm; maybe its performance could be improved?
Are there any better methods to permute a string?
Here is a non-recursive algorithm in C++ from the Wikipedia entry for unordered generation of permutations. For the string s of length n, for any k from 0 to n! - 1 inclusive, the following modifies s to provide a unique permutation (that is, different from those generated for any other k value on that range). To generate all permutations, run it for all n! k values on the original value of s.
#include <algorithm>
void permutation(int k, string &s)
{
for(int j = 1; j < s.size(); ++j)
{
std::swap(s[k % (j + 1)], s[j]);
k = k / (j + 1);
}
}
Here swap(s, i, j) swaps position i and j of the string s.
Why dont you try std::next_permutation() or std::prev_permutation()
?
Links:
std::next_permutation()
std::prev_permutation()
A simple example:
#include<string>
#include<iostream>
#include<algorithm>
int main()
{
std::string s="123";
do
{
std::cout<<s<<std::endl;
}while(std::next_permutation(s.begin(),s.end()));
}
Output:
123
132
213
231
312
321
I'd like to second Permaquid's answer. The algorithm he cites works in a fundamentally different way from the various permutation enumeration algorithms that have been offered. It doesn't generate all of the permutations of n objects, it generates a distinct specific permutation, given an integer between 0 and n!-1. If you need only a specific permutation, it's much faster than enumerating them all and then selecting one.
Even if you do need all permutations, it provides options that a single permutation enumeration algorithm does not. I once wrote a brute-force cryptarithm cracker, that tried every possible assignment of letters to digits. For base-10 problems, it was adequate, since there are only 10! permutations to try. But for base-11 problems took a couple of minutes and base-12 problems took nearly an hour.
I replaced the permutation enumeration algorithm that I had been using with a simple i=0--to--N-1 for-loop, using the algorithm Permaquid cited. The result was only slightly slower. But then I split the integer range in quarters, and ran four for-loops simultaneously, each in a separate thread. On my quad-core processor, the resulting program ran nearly four times as fast.
Just as finding an individual permutation using the permutation enumeration algorithms is difficult, generating delineated subsets of the set of all permutations is also difficult. The algorithm that Permaquid cited makes both of these very easy
In particular, you want std::next_permutation.
void permute(string elems, int mid, int end)
{
int count = 0;
while(next_permutation(elems.begin()+mid, elems.end()))
cout << << ++count << " : " << elems << endl;
}
... or something like that...
Any algorithm for generating permutations is going to run in polynomial time, because the number of permutations for characters within an n-length string is (n!). That said, there are some pretty simple in-place algorithms for generating permutations. Check out the Johnson-Trotter algorithm.
The Knuth random shuffle algorithm is worth looking into.
// In-place shuffle of char array
void shuffle(char array[], int n)
{
for ( ; n > 1; n--)
{
// Pick a random element to move to the end
int k = rand() % n; // 0 <= k <= n-1
// Simple swap of variables
char tmp = array[k];
array[k] = array[n-1];
array[n-1] = tmp;
}
}
Any algorithm that makes use of or generates all permutations will take O(N!*N) time, O(N!) at the least to generate all permutations and O(N) to use the result, and that's really slow. Note that printing the string is also O(N) afaik.
In a second you can realistically only handle strings up to a maximum of 10 or 11 characters, no matter what method you use. Since 11!*11 = 439084800 iterations (doing this many in a second on most machines is pushing it) and 12!*12 = 5748019200 iterations. So even the fastest implementation would take about 30 to 60 seconds on 12 characters.
Factorial just grows too fast for you to hope to gain anything by writing a faster implementation, you'd at most gain one character. So I'd suggest Prasoon's recommendation. It's easy to code and it's quite fast. Though sticking with your code is completely fine as well.
I'd just recommend that you take care that you don't inadvertantly have extra characters in your string such as the null character. Since that will make your code a factor of N slower.
I've written a permutation algorithm recently. It uses a vector of type T (template) instead of a string, and it's not super-fast because it uses recursion and there's a lot of copying. But perhaps you can draw some inspiration for the code. You can find the code here.
The only way to significantly improve performance is to find a way to avoid iterating through all the permutations in the first place!
Permuting is an unavoidably slow operation (O(n!), or worse, depending on what you do with each permutation), unfortunately nothing you can do will change this fact.
Also, note that any modern compiler will flatten out your recursion when optimisations are enabled, so the (small) performance gains from hand-optimising are reduced even further.
Do you want to run through all the permutations, or count the number of permutations?
For the former, use std::next_permutation as suggested by others. Each permutation takes O(N) time (but less amortized time) and no memory except its callframe, vs O(N) time and O(N) memory for your recursive function. The whole process is O(N!) and you can't do better than this, as others said, because you can't get more than O(X) results from a program in less than O(X) time! Without a quantum computer, anyway.
For the latter, you just need to know how many unique elements are in the string.
big_int count_permutations( string s ) {
big_int divisor = 1;
sort( s.begin(), s.end() );
for ( string::iterator pen = s.begin(); pen != s.end(); ) {
size_t cnt = 0;
char value = * pen;
while ( pen != s.end() && * pen == value ) ++ cnt, ++ pen;
divisor *= big_int::factorial( cnt );
}
return big_int::factorial( s.size() ) / divisor;
}
Speed is bounded by the operation of finding duplicate elements, which for chars can be done in O(N) time with a lookup table.
I don't think this is better, but it does work and does not use recursion:
#include <iostream>
#include <stdexcept>
#include <tr1/cstdint>
::std::uint64_t fact(unsigned int v)
{
::std::uint64_t output = 1;
for (unsigned int i = 2; i <= v; ++i) {
output *= i;
}
return output;
}
void permute(const ::std::string &s)
{
using ::std::cout;
using ::std::uint64_t;
typedef ::std::string::size_type size_t;
static unsigned int max_size = 20; // 21! > 2^64
const size_t strsize = s.size();
if (strsize > max_size) {
throw ::std::overflow_error("This function can only permute strings of size 20 or less.");
} else if (strsize < 1) {
return;
} else if (strsize == 1) {
cout << "0 : " << s << '\n';
} else {
const uint64_t num_perms = fact(s.size());
// Go through each permutation one-by-one
for (uint64_t perm = 0; perm < num_perms; ++perm) {
// The indexes of the original characters in the new permutation
size_t idxs[max_size];
// The indexes of the original characters in the new permutation in
// terms of the list remaining after the first n characters are pulled
// out.
size_t residuals[max_size];
// We use div to pull our permutation number apart into a set of
// indexes. This holds what's left of the permutation number.
uint64_t permleft = perm;
// For a given permutation figure out which character from the original
// goes in each slot in the new permutation. We start assuming that
// any character could go in any slot, then narrow it down to the
// remaining characters with each step.
for (unsigned int i = strsize; i > 0; permleft /= i, --i) {
uint64_t taken_char = permleft % i;
residuals[strsize - i] = taken_char;
// Translate indexes in terms of the list of remaining characters
// into indexes in terms of the original string.
for (unsigned int o = (strsize - i); o > 0; --o) {
if (taken_char >= residuals[o - 1]) {
++taken_char;
}
}
idxs[strsize - i] = taken_char;
}
cout << perm << " : ";
for (unsigned int i = 0; i < strsize; ++i) {
cout << s[idxs[i]];
}
cout << '\n';
}
}
}
The fun thing about this is that the only state it uses from permutation to permutation is the number of the permutation, the total number of permutations, and the original string. That means it can be easily encapsulated in an iterator or something like that without having to carefully preserve the exact correct state. It can even be a random access iterator.
Of course ::std::next_permutation stores the state in the relationships between elements, but that means it can't work on unordered things, and I would really wonder what it does if you have two equal things in the sequence. You can solve that by permuting indexes of course, but that adds slightly more complication.
Mine will work with any random access iterator range provided it's short enough. And if it isn't, you'll never get through all the permutations anyway.
The basic idea of this algorithm is that every permutation of N items can be enumerated. The total number is N! or fact(N). And any given permutation can be thought of as a mapping of source indices from the original sequence into a set of destination indices in the new sequence. Once you have an enumeration of all permutations the only thing left to do is map each permutation number into an actual permutation.
The first element in the permuted list can be any of the N elements from the original list. The second element can be any of the N - 1 remaining elements, and so on. The algorithm uses the % operator to pull apart the permutation number into a set of selections of this nature. First it modulo's the permutation number by N to get a number from [0,N). It discards the remainder by dividing by N, then it modulo's it by the size of the list - 1 to get a number from [0,N-1) and so on. That is what the for (i = loop is doing.
The second step is translating each number into an index into the original list. The first number is easy because it's just a straight index. The second number is an index into a list that contains every element but the one removed at the first index, and so on. That is what the for (o = loop is doing.
residuals is a list of indices into the successively smaller lists. idxs is a list of indices into the original list. There is a one-one mapping between values in residuals and idxs. They each represent the same value in different 'coordinate spaces'.
The answer pointed to by the answer you picked has the same basic idea, but has a much more elegant way of accomplishing the mapping than my rather literal and brute force method. That way will be slightly faster than my method, but they are both about the same speed and they both have the same advantage of random access into permutation space which makes a whole number of things easier, including (as the answer you picked pointed out) parallel algorithms.
Actually you can do it using Knuth shuffling algo!
// find all the permutations of a string
// using Knuth radnom shuffling algorithm!
#include <iostream>
#include <string>
template <typename T, class Func>
void permutation(T array, std::size_t N, Func func)
{
func(array);
for (std::size_t n = N-1; n > 0; --n)
{
for (std::size_t k = 0; k <= n; ++k)
{
if (array[k] == array[n]) continue;
using std::swap;
swap(array[k], array[n]);
func(array);
}
}
}
int main()
{
while (std::cin.good())
{
std::string str;
std::cin >> str;
permutation(str, str.length(), [](std::string const &s){
std::cout << s << std::endl; });
}
}
This post: http://cplusplus.co.il/2009/11/14/enumerating-permutations/ deals with permuting just about anything, not only strings. The post itself and the comments below are pretty informative and I wouldn't want to copy&paste..
If you are interested in permutation generation I did a research paper on it a while back : http://www.oriontransfer.co.nz/research/permutation-generation
It comes complete with source code, and there are 5 or so different methods implemented.
Even I found it difficult to understand that recursive version of the first time and it took me some time to search for a berre way.Better method to find (that I can think of) is to use the algorithm proposed by Narayana Pandita. The basic idea is:
First sort the given string in no-decreasing order and then find the index of the first element from the end that is less than its next character lexicigraphically. Call this element index the 'firstIndex'.
Now find the smallest character which is greater thn the element at the 'firstIndex'. Call this element index the 'ceilIndex'.
Now swap the elements at 'firstIndex' and 'ceilIndex'.
Reverse the part of the string starting from index 'firstIndex+1' to the end of the string.
(Instead of point 4) You can also sort the part of the string from index 'firstIndex+1' to the end of the string.
Point 4 and 5 do the same thing but the time complexity in case of point 4 is O(n*n!) and that in case of point 5 is O(n^2*n!).
The above algorithm can even be applied to the case when we have duplicate characters in the string. :
The code for displaying all the permutation of a string :
#include <iostream>
using namespace std;
void swap(char *a, char *b)
{
char tmp = *a;
*a = *b;
*b = tmp;
}
int partition(char arr[], int start, int end)
{
int x = arr[end];
int i = start - 1;
for(int j = start; j <= end-1; j++)
{
if(arr[j] <= x)
{
i = i + 1;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i+1], &arr[end]);
return i+1;
}
void quickSort(char arr[], int start, int end)
{
if(start<end)
{
int q = partition(arr, start, end);
quickSort(arr, start, q-1);
quickSort(arr, q+1, end);
}
}
int findCeilIndex(char *str, int firstIndex, int n)
{
int ceilIndex;
ceilIndex = firstIndex+1;
for (int i = ceilIndex+1; i < n; i++)
{
if(str[i] >= str[firstIndex] && str[i] <= str[ceilIndex])
ceilIndex = i;
}
return ceilIndex;
}
void reverse(char *str, int start, int end)
{
while(start<=end)
{
char tmp = str[start];
str[start] = str[end];
str[end] = tmp;
start++;
end--;
}
}
void permutate(char *str, int n)
{
quickSort(str, 0, n-1);
cout << str << endl;
bool done = false;
while(!done)
{
int firstIndex;
for(firstIndex = n-2; firstIndex >=0; firstIndex--)
{
if(str[firstIndex] < str[firstIndex+1])
break;
}
if(firstIndex<0)
done = true;
if(!done)
{
int ceilIndex;
ceilIndex = findCeilIndex(str, firstIndex, n);
swap(&str[firstIndex], &str[ceilIndex]);
reverse(str, firstIndex+1, n-1);
cout << str << endl;
}
}
}
int main()
{
char str[] = "mmd";
permutate(str, 3);
return 0;
}
Here's one I just rustled up!!
void permute(const char* str, int level=0, bool print=true) {
if (print) std::cout << str << std::endl;
char temp[30];
for (int i = level; i<strlen(str); i++) {
strcpy(temp, str);
temp[level] = str[i];
temp[i] = str[level];
permute(temp, level+1, level!=i);
}
}
int main() {
permute("1234");
return 0;
}
This is not the best logic, but then, i am a beginner. I'll be quite happy and obliged if anyone gives me suggestions on this code
#include<iostream.h>
#include<conio.h>
#include<string.h>
int c=1,j=1;
int fact(int p,int l)
{
int f=1;
for(j=1;j<=l;j++)
{
f=f*j;
if(f==p)
return 1;
}
return 0;
}
void rev(char *a,int q)
{
int l=strlen(a);
int m=l-q;
char t;
for(int x=m,y=0;x<q/2+m;x++,y++)
{
t=a[x];
a[x]=a[l-y-1];
a[l-y-1]=t;
}
c++;
cout<<a<<" ";
}
int perm(char *a,int f,int cd)
{
if(c!=f)
{
int l=strlen(a);
rev(a,2);
cd++;
if(c==f)return 0;
if(cd*2==6)
{
for(int i=1;i<=c;i++)
{
if(fact(c/i,l)==1)
{
rev(a,j+1);
rev(a,2);
break;
}
}
cd=1;
}
rev(a,3);
perm(a,f,cd);
}
return 0;
}
void main()
{
clrscr();
char *a;
cout<<"\n\tEnter a Word";
cin>>a;
int f=1;
for(int o=1;o<=strlen(a);o++)
f=f*o;
perm(a,f,0);
getch();
}
**// Prints all permutation of a string**
#include<bits/stdc++.h>
using namespace std;
void printPermutations(string input, string output){
if(input.length() == 0){
cout<<output <<endl;
return;
}
for(int i=0; i<=output.length(); i++){
printPermutations(input.substr(1), output.substr(0,i) + input[0] + output.substr(i));
}
}
int main(){
string s = "ABC";
printPermutations(s, "");
return 0;
}
Here yet another recursive function for string permutations:
void permute(string prefix, string suffix, vector<string> &res) {
if (suffix.size() < 1) {
res.push_back(prefix);
return;
}
for (size_t i = 0; i < suffix.size(); i++) {
permute(prefix + suffix[i], suffix.substr(0,i) + suffix.substr(i + 1), res);
}
}
int main(){
string str = "123";
vector<string> res;
permute("", str, res);
}
The function collects all permutations in vector res.
The idea can be generalized for different type of containers using templates and iterators:
template <typename Cont1_t, typename Cont2_t>
void permute(typename Cont1_t prefix,
typename Cont1_t::iterator beg, typename Cont1_t::iterator end,
Cont2_t &result)
{
if (beg == end) {
result.insert(result.end(), prefix);
return;
}
for (auto it = beg; it != end; ++it) {
prefix.insert(prefix.end(), *it);
Cont1_t tmp;
for (auto i = beg; i != end; ++i)
if (i != it)
tmp.insert(tmp.end(), *i);
permute(prefix, tmp.begin(), tmp.end(), result);
prefix.erase(std::prev(prefix.end()));
}
}
int main()
{
string str = "123";
vector<string> rStr;
permute<string, vector<string>>("", str.begin(), str.end(), rStr);
vector<int>vint = { 1,2,3 };
vector<vector<int>> rInt;
permute<vector<int>, vector<vector<int>>>({}, vint.begin(), vint.end(), rInt);
list<long> ll = { 1,2,3 };
vector<list<long>> vlist;
permute<list<long>, vector<list<long>>>({}, ll.begin(), ll.end(), vlist);
}
This may be an interesting programming exercise, but in production code you should use a non recusrive version of permutation , like next_permutation.
//***************anagrams**************//
//************************************** this code works only when there are no
repeatations in the original string*************//
#include<iostream>
using namespace std;
int counter=0;
void print(char empty[],int size)
{
for(int i=0;i<size;i++)
{
cout<<empty[i];
}
cout<<endl;
}
void makecombination(char original[],char empty[],char comb[],int k,int& nc,int size)
{
nc=0;
int flag=0;
for(int i=0;i<size;i++)
{
flag=0; // {
for(int j=0;j<k;j++)
{
if(empty[j]==original[i]) // remove this code fragment
{ // to print permutations with repeatation
flag=1;
break;
}
}
if(flag==0) // }
{
comb[nc++]=original[i];
}
}
//cout<<"checks ";
// print(comb,nc);
}
void recurse(char original[],char empty[],int k,int size)
{
char *comb=new char[size];
int nc;
if(k==size)
{
counter++;
print(empty,size);
//cout<<counter<<endl;
}
else
{
makecombination(original,empty,comb,k,nc,size);
k=k+1;
for(int i=0;i<nc;i++)
{
empty[k-1]=comb[i];
cout<<"k = "<<k<<" nc = "<<nc<<" empty[k-1] = "<<empty[k-1]<<endl;//checks the value of k , nc, empty[k-1] for proper understanding
recurse(original,empty,k,size);
}
}
}
int main()
{
const int size=3;
int k=0;
char original[]="ABC";
char empty[size];
for(int f=0;f<size;f++)
empty[f]='*';
recurse(original,empty,k,size);
cout<<endl<<counter<<endl;
return 0;
}